泛型就一句话:不同的数据类型,要执行同样的逻辑(行为),就用泛型。
1】我们常用的比如List, Dictionary<Key,Value> 都是泛型
2】泛型行为只能用类型,不能对类型初始化(例外:反射技术)
3】default关键字:
private T1 obj;
private void TestFunc()
{
obj = default(T1); //给obj赋T1类型的默认值(因为不确定是值类型还是引用类型)
}
4】泛型的约束类型
泛型可以约束使用到的数据类型,格式如下(可提供多个约束类型,以逗号分隔)
class MyGenericClass<T> where T : constraint1, constraint2
{}
可以定义多个类型的约束
class MyGenericClass<T1, T2> where T1 : constraint1, constraint2 where T2 : constraint3
{}
约束必须出现在继承之后,比如:
class MyGenericClass<T1, T2> : MyBaseClass
where T1 : constraint1, constraint2 where T2 : constraint3
{}
泛型类型的约束如下:
注意:如果用new()用作约束,它必须是最后一个约束。
可以通过base-class约束,把一个类型参数用作另一个类型参数的约束,例如:
class MyGenericClass<T1, T2> where T2 : T1
{}
其中T2必须与T1的类型相同,或者继承自T1,这种称为裸类型约束,表示一个泛型类型参数用作另一个类型参数的约束。
有一点需要注意,类型约束不能循环,例如
class MyGenericClass<T1, T2> where T2 : T1 where T1 : T2
{}
5】泛型结构
定义一个泛型结构如下,都是一样的。
public struct MyStruct<T1,T2>
{
public T1 op1;
public T2 op2;
}
6】泛型接口
定义一个泛型接口如下,都是一样的。
interface MyInterface<T>
{
}
7】定义泛型方法
public voud GetNum1<T>(T op)
{}
public T GetTDefault<T>(T op)
{}
8】定义泛型委托
delegate void MyDelegate1<T>(T op);
delegate T MyDelegate2<T>(T op);
delegate T1 MyDelegate3<T1, T2>(T1 op1, T2 op2) where T2 : T1;
9】变体
变体(variance)是协变(covariance)和抗变(contravariance)的统称。
这项技术用的很少,可以把他理解成泛型的多态,直接上干货,有不明白并且还感兴趣的可以自己百度查下详细的讲解
变体是类似于多态性的一个概念,但应用于类型参数。它允许使用一个泛型类型替代另一个泛型类型,这些泛型类型仅在所使用的泛型类型参数上有区别。
协变允许在两种类型之间转换,其中目标类型有1个类型参数,它是源类型的类型参数的基类。(可以理解成多态性中的子转父)
比如:
//首先声明: Cow类 继承自 Animal
//解释,类的多态就是Cow 可以转 Animal,并使用Animal中的方法(属性)
//而协变同样,只不过这里的Cow和Animal都是泛型的类型参数
static void main(string[] args)
{
List<Cow> cows = new List<Cow>();
cows.Add(new Cow("cow1"));
cows.Add(new Cow("cow2"));
ListAnimals(cows);
}
static void ListAnimals(IEnumrable<Animals> animals)
{
foreach(Animal ani in animals)
{
.....
}
}
[要把泛型类型参数定义为协变,可在类型定义中使用out关键字,只能用作返回类型和属性get访问器的类型],例如:
public interface Imethane<out T>
{}
抗变与协变相反,它允许在两种类型之间转换,其中目标类型有1个类型参数,它是源类型的类型参数的派生类。(可以理解成多态性中的父转子)
[要把泛型类型参数定义为抗变,可在类型定义中使用in关键字,只能用作方法的参数],例如:
public interface Imethane<in T>
{}
一个小知识点:
10】List 中的sort排序里面的自定义方法返回值的含义
return 1: 向前换位( left 移到right 后面)
return -1: 向后换位( left 移到 right的前面)
return 0: 不变