默认值
现在我们先新建一个实例,在这定义了一个泛型类Test<T>,泛型类中有一个GetModel方法返回的是一个T类型
public class Test<T> { public T GetModle() { T model = default(T); return model; } }
T model = default(T);
通过default关键字,将null赋予引用类型,将0赋予值类型
约束
下面给出了一些泛型约束的条件
继承
1.泛型类型可以实现一个泛型接口,也可以派生自一个泛型类
2.派生类可以是泛型类或非泛型类
定义一个抽象的泛型基类
public abstract class Calc<T> { public abstract T Add(T x, T y); public abstract T Sub(T x, T y); }
派生类中可以定义非泛型类
class IntCalc:Calc<int> { public override int Add(int x, int y) { return x + y; } public override int Sub(int x, int y) { return x - y; } }
协变和逆变
感觉协变类似多态
首先我们定义一个简单的类
public class People { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } }
class Chinese:People { public string Hukou { get; set; } }
People p = new Chinese();
这样子我们就简单的通过继承并且实现了类型的隐式转换
Chinese c = (Chinese)p;
这是类型的强制转换
在泛型接口中,我们是不是也可以做如下的假设呢,首先我们定义一个泛型接口
interface IMyInterface<T> { }
如果上面的类型的隐式和强制转换都存在的话,下面的代码是可以编译通过的
IMyInterface<People> p=new IMyInterface<Chinese>(); IMyInterface<Chinese> c=(IMyInterface<Chinese>)p;
但是在.net4.0(c#4.0之前)也就是在泛型接口中是没有所谓的上述的定义,所以在c#4.0后微软就有了协变和逆变的概念了
协变:泛型接口从子类向父类的变化
逆变:泛型接口父类向子类的变化
条件:通过在泛型接口的声明中加入int和out来修饰泛型参数T
协变和逆变的注意事项:
1. 只有接口和委托支持协变和逆变(如Func<out TResult>,Action<in T>),类或泛型方法的类型参数都不支持协变和逆变。
2. 协变和逆变只适用于引用类型,值类型不支持协变和逆变(因为可变性存在一个引用转换,而值类型变量存储的就是对象本身,而不是对象的引用),所以List<int>无法转化为Ienumerable<object>.
3. 必须显示用in或out来标记类型参数。
泛型方法
泛型方法可以在非泛型类中定义
一个简单的泛型方法的使用例子
static void Swap<T>(ref T x, ref T y) { T temp; temp = x; x = y; y = temp; }
int x = 4; int y = 5; Swap<int>(ref x,ref y); Console.WriteLine(string.Format("x的值{0},y的值{1}", x, y));
在定义一个简单的例子
public static decimal Accumulate<TAccount>(IEnumerable<TAccount> source) where TAccount : IAccount { decimal sum = 0; foreach (TAccount a in source) { sum += a.Balance; } return sum; }
泛型方法的重载
public void Foo<T>(T obj) { Console.WriteLine("Foo<T>(T obj),obj type:{0}", obj.GetType().Name); } public void Foo(int x) { Console.WriteLine("Foo(int x)"); }