首页 > 代码库 > c#之泛型

c#之泛型

默认值

现在我们先新建一个实例,在这定义了一个泛型类Test<T>,泛型类中有一个GetModel方法返回的是一个T类型

public class Test<T>    {        public T GetModle()        {            T model = default(T);            return model;        }    }
T model = default(T);

通过default关键字,将null赋予引用类型,将0赋予值类型

约束

下面给出了一些泛型约束的条件

image

继承

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)");       }

在编译期间,如果传递一个int类型,就选择带int参数的方法,对于其他类型,编译器会选择其他方法

c#之泛型