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#)