概述
泛型使得程序在设计的时候,不必设计其具体的参数,其具体的参数可以延迟到需要的时候
声明或调用。总体上是一种延迟思想,延迟一切可以推迟的。
定义
一种自定义的强类型化的集合类技术,这种集合类派生于CollectBase,并且可以拥有自己的
视线方法来增删查集合的每个成员。因此,每次创建需要包含在集合中的新类时,需要执行任务,
创建一个新的集合类,继承于CollectBase,他可包含新类型的项,实现所有需要的方法
旧方法
CollectionClass items = new CollectionClass;
items.append(new ItemClass);
新方法
CollectionClass<ItemClass> items = new CollectionClass<ItemClass>();
items.append(new ItemClass());
但是,泛型不仅适用于集合、并且不限于类,还可泛型接口、泛型方法、泛型委托。不但能
提高代码的灵活性,还能显著的缩短代码的开发周期。
注意:
C#的泛型不同于C++的泛型,C++泛型是编译期间的多态,C#的所有操作都是在运行中进行的。.Net运行库允许在需要时动态的生成泛型类,未使用时就不会有存在泛型类。
用法
可空类型
泛型使用System.Nullable<T>类型提供了使值类型为空的一种方式。
System.Nullable<int> nullableint;
nullableint = null;
如果bullableint是int类型这是让编译器诧异的操作!
等价于:
System.Nullable<int> nullableint ;
nullableint = new System.Nullable<int>();
为空判断:
?(nullableint == null);
非空判断
?(nullableint.HasValue)
可为空类型简写: System.Nullable<int> nullableint = int ? nullableint;
System.Nullable<int> nullint = new System.Nullable<int>();
if (nullint.HasValue)
{
Console.WriteLine("AAA已经初始化过了");
}
if (nullint == null)
{
Console.WriteLine("还没有初始化过");
}nullint = 10;
if (nullint.HasValue)
{
Console.WriteLine("BBB已经初始化过了");
}
注意:可空类型的转换必须显示转换,举例当op是null,就会捕获System.Invalid-OperationException
int ? op=5;
int num = (int) op*2;
//int num = op.Value *2;
??运算符(空接合运算符)
类似于三目运算符,更加简化代码。若op1为null返回op1,否则返回op2
op1 ?? op2
op1 == null ? op2 : op1
?.运算符(空条件运算符)
避免繁杂的空值检查造成代码歧义
int count = customer.orders.Count();
如果order为空会抛出异常,是否和我一样懒得重复的异常处理,那就
int ? count = customer.orders ?.C ount();
甚至可以融汇??运算符
int ?count = customer.orders?.Count() ?? 0;
System.Collections.Generic名称空间
这个集合下面包含用于处理集合的泛型类型,泛型集合类型举例:List<T>;Dictionary<K,V>;
这个namespace下可处理泛型列表的排序搜索
定义泛型类型
class MyGenericClass<T1,T2,T3>{.......}
default关键字
常常因为泛型实例不清楚是值类型还是引用类型,因此产生关键字default;
innerT1Object = default(T1);//这里 innerT1Object是一个泛型成员
约束类型
约束泛型为指定类型;
class MyGenericClass<T> where T:constrant1,constrant2...{...}
class MyGenericClass<T1,T2>where T1 : constrant1 where T2 : constrant2{...}
约束必须出现在继承说明符后面;
base-class约束
class MyGenericClass<T1,T2> where T2:T1{....}
约束从基类继承
public class Farm<T> : IEnumerable<T> where T : Animal{}
class SuperFarm<T> : Farm<T> where T:SuperCow{}//因为SuperCow是Animal的派生类所以合法;
但是,以下则不合法
class SuperFarm<T> :Farm<T> where T:struct{}
定义泛型接口
interface MyFarmingInterface<T> where T:Animal
{
bool OneMeathod(T animal1,T animal2);
}
定义泛型方法
public class Defaulter
{
public T GetDefault<T>() =>default(T);
}
定义泛型委托
public delegate T1 MyDelegate<T1,T2>(T2 op1,T1 op2) where T1 : T2;
变体
运行时多态
Cow myCow = new Cow("Geronimo");
Animal myAnimal = myCow;
但是下面的泛型接口第二行应用却不合法,
IMethod<Cow> cowMethod = myCow;
IMethod<Animal> animalMethod= cowMethod;
因为泛型的类型参数都是不变的,为了使第二行生效,需要引入协变,可以使得IMethod<Cow>和IMethod<Animal>建立一种联系,这样便可以实现接口的多态性。
协变就是不能用接口实现父类到子类的隐式转换;(记忆:父子关系不和“协”,父亲不接纳儿子)
同理下式第二行引用也不合法:
IMethod<Cow> cowMethod = myCow;
IMethod<SuperCow> superCowMethod = cowMethod;
抗变就是不能用接口实现子类到父类的隐式转换;(记忆:反抗时期的儿子,儿子和父亲对抗)
总结
下次总结,睡了睡了。