C#2.0泛型编程之强制类型转换、继承和泛型
2015-06-09 17:19
363 查看
泛型和强制类型转换
隐式强制转换
C#编译器只允许将泛型参数隐式强制转换到object或泛型参数的约束指定的类型,代码如下
interface IMyInterface
{
//
}
class MyClass
{
//
}
class ConvertOfTypeDemo<T> where T : MyClass, IMyInterface
{
void MyMethod(T t)
{
IMyInterface obj1 = t;
MyClass obj2 = t;
Object obj3 = t;
}
}
显式强制转换
C#编译器允许你将泛型参数显式强制转换到其他任何接口,但不能转换到类,代码如下
在这里我们可以采取一种措施来避免编译时出现上述错误,由于泛型参数可以隐式转换object类型,那么我们在这里可以定义一个临时变量来解决此事,代码如下
interface IMyInterface
{
//
}
class MyClass
{
//
}
class ConvertOfTypeDemo<T>
{
void MyMethod(T t)
{
IMyInterface obj1 = (IMyInterface)t;
object tmp = t;
MyClass obj2 = (MyClass)tmp;
}
}
但是在上面的代码中,会又有可能出现值类型参数的装箱与拆箱以及类型安全得不到保证,这就违反了我们使用泛型参数的初衷,虽然上述代码可以在编译时通过,但是在运行时有可能会报错,所以也不推荐使用。
不用说强制类型转换的危险性大家都知道,如果泛型参数的实参不是派生自您要显式强制转换到的类型,则有可能报错,为了解决这个问题,我们一般采用is和as操作符。代码如下
继承和泛型
若子类不是泛型类,那在泛型基类派生时,基类必须提供类型实参,而不是泛型参数,如下
若子类是泛型类,而非具体的类型实参,则可以使用子类的泛型参数作为基类泛型参数指定的类型
public class MyBaseClass<T>
{
}
//MyBaseClass类中的泛型参数(非类型实参)必须同SubClass1中相同,基类泛型参数为类型实参的除外
public class SubClass1<K> : MyBaseClass<K>
{
}
//可以编译通过,原因是如果基类指定了类型实参,就相当于泛型继承自一个非泛型类
public class SubClass3<K> : MyBaseClass<int>
{
}
//错误 找不到类型或命名空间名称“T”
public class SubClass2<K> : MyBaseClass<T>
{
}
在使用子类泛型参数时,必须在子类级别再重复在基类级别规定的任何约束,如下
public class MyBaseClass<T> where T:new()
{
}
public class MySubClass<T> : MyBaseClass<T> where T : new()
{
}
/********************************************************************
错误 “T”必须是具有公共的无参数构造函数的非抽象类型,
* 才能用作泛型类型或方法“Demo3.MyBaseClass<T>”中的参数“T”
*********************************************************************/
public class MySubClass1<T> : MyBaseClass<T>
{
}
虚方法的继承
若子类不是泛型类,虚方法重写代码如下
若子类是泛型类,基类也是泛型类的虚方法重写,代码如下
public class MyBaseClass<T>
{
public virtual T SomeMethod()
{
}
}
public class MySubClass<T> : MyBaseClass<T>
{
public override T SomeMethod()
{
}
}
泛型抽象类、泛型抽象方法和泛型接口的使用
public interface ISomeInterface<T>
{
T SomeMethod(T t);
}
public abstract class MyBaseClass<T>
{
public abstract T SomeMethod(T t);
}
public class MySubClass<T> : MyBaseClass<T>
{
public override T SomeMethod(T t)
{
}
}
泛型类型中泛型参数的运算符的实现
由于在运行时不能确定泛型参数的实参类型,所以不能直接对泛型参数进行加、减、乘和除等运算操作。但是我们可以通过定义泛型操作,使用抽象方法(最好使用接口)进行补偿,由于抽象方法的内部不能有任何代码,因此可以在基类级别指定泛型操作,并且在子类级别提供具体的类型和实现。
用抽象类和抽象方法实现运算符操作,代码如下
用接口实现泛型参数四则运算操作
public interface IBaseCalculator<T>
{
T Add(T arg1, T arg2);
T Subtract(T arg1, T arg2);
T Mutiple(T arg1, T arg2);
T Divide(T arg1, T arg2);
}
public class SubCalculator : IBaseCalculator<int>
{
public int Add(int arg1, int arg2)
{
return arg1 + arg2;
}
public int Subtract(int arg1, int arg2)
{
return arg1 - arg2;
}
public int Mutiple(int arg1, int arg2)
{
return arg1 * arg2;
}
public int Divide(int arg1, int arg2)
{
return arg1 / arg2;
}
}
隐式强制转换
C#编译器只允许将泛型参数隐式强制转换到object或泛型参数的约束指定的类型,代码如下
interface IMyInterface
{
//
}
class MyClass
{
//
}
class ConvertOfTypeDemo<T> where T : MyClass, IMyInterface
{
void MyMethod(T t)
{
IMyInterface obj1 = t;
MyClass obj2 = t;
Object obj3 = t;
}
}
显式强制转换
C#编译器允许你将泛型参数显式强制转换到其他任何接口,但不能转换到类,代码如下
interface IMyInterface { // } class MyClass { // } class ConvertOfTypeDemo<T> { void MyMethod(T t) { IMyInterface obj1 = (IMyInterface)t; MyClass obj2 = (MyClass)t;//无法将类型“T”转换为“Demo3.MyClass” } }
在这里我们可以采取一种措施来避免编译时出现上述错误,由于泛型参数可以隐式转换object类型,那么我们在这里可以定义一个临时变量来解决此事,代码如下
interface IMyInterface
{
//
}
class MyClass
{
//
}
class ConvertOfTypeDemo<T>
{
void MyMethod(T t)
{
IMyInterface obj1 = (IMyInterface)t;
object tmp = t;
MyClass obj2 = (MyClass)tmp;
}
}
但是在上面的代码中,会又有可能出现值类型参数的装箱与拆箱以及类型安全得不到保证,这就违反了我们使用泛型参数的初衷,虽然上述代码可以在编译时通过,但是在运行时有可能会报错,所以也不推荐使用。
不用说强制类型转换的危险性大家都知道,如果泛型参数的实参不是派生自您要显式强制转换到的类型,则有可能报错,为了解决这个问题,我们一般采用is和as操作符。代码如下
interface IMyInterface { // } class MyClass { // } class ConvertOfTypeDemo<T> { void MyMethod(T t) { if (t is int) { // } if (t is MyClass) { // } if (t is IMyInterface) { // } string str0 = t as string; if (str0 != null) { // } IMyInterface m = t as IMyInterface; if (m != null) { // } MyClass my = t as MyClass; if (my != null) { // } } }
继承和泛型
若子类不是泛型类,那在泛型基类派生时,基类必须提供类型实参,而不是泛型参数,如下
public class MyBaseClass<T> { } public class SubClass1 : MyBaseClass<int> { } //错误 找不到类型或命名空间名称“T” public class SubClass2 : MyBaseClass<T> { }
若子类是泛型类,而非具体的类型实参,则可以使用子类的泛型参数作为基类泛型参数指定的类型
public class MyBaseClass<T>
{
}
//MyBaseClass类中的泛型参数(非类型实参)必须同SubClass1中相同,基类泛型参数为类型实参的除外
public class SubClass1<K> : MyBaseClass<K>
{
}
//可以编译通过,原因是如果基类指定了类型实参,就相当于泛型继承自一个非泛型类
public class SubClass3<K> : MyBaseClass<int>
{
}
//错误 找不到类型或命名空间名称“T”
public class SubClass2<K> : MyBaseClass<T>
{
}
在使用子类泛型参数时,必须在子类级别再重复在基类级别规定的任何约束,如下
public class MyBaseClass<T> where T:new()
{
}
public class MySubClass<T> : MyBaseClass<T> where T : new()
{
}
/********************************************************************
错误 “T”必须是具有公共的无参数构造函数的非抽象类型,
* 才能用作泛型类型或方法“Demo3.MyBaseClass<T>”中的参数“T”
*********************************************************************/
public class MySubClass1<T> : MyBaseClass<T>
{
}
虚方法的继承
若子类不是泛型类,虚方法重写代码如下
public class MyBaseClass<T> { public virtual T SomeMethod() { } } public class MySubClass : MyBaseClass<int> { public override int SomeMethod() { } }
若子类是泛型类,基类也是泛型类的虚方法重写,代码如下
public class MyBaseClass<T>
{
public virtual T SomeMethod()
{
}
}
public class MySubClass<T> : MyBaseClass<T>
{
public override T SomeMethod()
{
}
}
泛型抽象类、泛型抽象方法和泛型接口的使用
public interface ISomeInterface<T>
{
T SomeMethod(T t);
}
public abstract class MyBaseClass<T>
{
public abstract T SomeMethod(T t);
}
public class MySubClass<T> : MyBaseClass<T>
{
public override T SomeMethod(T t)
{
}
}
泛型类型中泛型参数的运算符的实现
由于在运行时不能确定泛型参数的实参类型,所以不能直接对泛型参数进行加、减、乘和除等运算操作。但是我们可以通过定义泛型操作,使用抽象方法(最好使用接口)进行补偿,由于抽象方法的内部不能有任何代码,因此可以在基类级别指定泛型操作,并且在子类级别提供具体的类型和实现。
用抽象类和抽象方法实现运算符操作,代码如下
public abstract class BaseCalculator<T> { public abstract T Add(T arg1, T arg2); public abstract T Subtract(T arg1, T arg2); public abstract T Mutiple(T arg1, T arg2); public abstract T Divide(T arg1, T arg2); } public class SubCalculator : BaseCalculator<int> { public override int Add(int arg1, int arg2) { return arg1 + arg2; } public override int Subtract(int arg1, int arg2) { return arg1 - arg2; } public override int Mutiple(int arg1, int arg2) { return arg1 * arg2; } public override int Divide(int arg1, int arg2) { return arg1 / arg2; } }
用接口实现泛型参数四则运算操作
public interface IBaseCalculator<T>
{
T Add(T arg1, T arg2);
T Subtract(T arg1, T arg2);
T Mutiple(T arg1, T arg2);
T Divide(T arg1, T arg2);
}
public class SubCalculator : IBaseCalculator<int>
{
public int Add(int arg1, int arg2)
{
return arg1 + arg2;
}
public int Subtract(int arg1, int arg2)
{
return arg1 - arg2;
}
public int Mutiple(int arg1, int arg2)
{
return arg1 * arg2;
}
public int Divide(int arg1, int arg2)
{
return arg1 / arg2;
}
}
相关文章推荐
- c#调用COM组件
- JAVA泛型—— 3fe8 转
- JAVA泛型详解——转
- C#中抽象方法与虚拟方法的区别
- c#中虚函数的相关使用方法
- C#实现多线程的同步方法实例分析
- C#中尾递归的使用、优化及编译器优化
- PostgreSQL教程(三):表的继承和分区表详解
- C#通用邮件发送类分享
- C#中this的用法集锦
- C#中Equality和Identity浅析
- C#生成饼形图及添加文字说明实例代码
- C#判等对象是否相等的方法汇总
- C#简单的向量用法实例教程
- C#托管堆对象实例包含内容分析
- C#实现按照指定长度在数字前补0方法小结
- C#虚方法的声明和使用实例教程
- C#获取文件夹及文件的大小与占用空间的方法
- C#定义简单的反射工厂实例分析
- C#数字图象处理之肤色检测的方法