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赋予值类型

约束

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

c#之泛型

继承

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#之泛型

上一篇:C# 接口


下一篇:分享到QQ空间 API