基于泛型,我们得以将类型参数化,以便更大范围地进行代码复用。同时,它减少了泛型类及泛型方法中的转型,确保了类型安全。委托本身是一种引用类型,它保存的也是托管堆中对象的引用,只不过这个引用比较特殊,它是对方法的引用。事件本身也是委托,它是委托组,C#中提供了关键字event来对事件进行特别区分。 一旦我们开始编写稍微复杂的C#代码,就肯定离不开泛型、委托和事件。
1.总是优先考虑泛型
泛型的优点是多方面的,无论是泛型类还是泛型方法都同时具备可重用性、类型安全和高效率等特性,这都是非泛型类和非泛型方法无法具备的
2.避免在泛型类型中声明静态成员
- 实际上,随着你为T指定不同的数据类型,MyList<T>相应地也变成了不同的数据类型,在它们之间是不共享静态成员的。
- 但是若T所指定的数据类型是一致的,那么两个泛型对象间还是可以共享静态成员的,如上文的list1和list2。但是,为了规避因此而引起的混淆,仍旧建议在实际的编码工作中,尽量避免声明泛型类型的静态成员。
非泛型类型中的泛型方法并不会在运行时的本地代码中生成不同的类型。
例如:
static void Main(string[]args) { Console.WriteLine(MyList.Func<int>()); Console.WriteLine(MyList.Func<int>()); Console.WriteLine(MyList.Func<string>()); } class MyList { static int count; public static int Func<T>() { return count++; }} 输出 0 ;1;2
3.为泛型参数设定约束
在编码过程中,应该始终考虑为泛型参数设定约束。约束使泛型参数成为一个实实在在的“对象”,让它具有了我们想要的行为和属性,而不仅仅是一个ob-ject。
指定约束示例:
- 指定参数是值类型。(除Nullable外) where T:struct
- 指定参数是引用类型 。 where T:class
-
指定参数具有无参数的公共构造方法。 where T:new()
注意,CLR目前只支持无参构造方法约束。
- 指定参数必须是指定的基类,或者派生自指定的基类。
- 指定参数必须是指定的接口,或者实现指定的接口。
- 指定T提供的类型参数必须是为U提供的参数,或者派生自为U提供的参数。 where T:U
-
可以对同一类型的参数应用多个约束,并且约束自身可以是泛型类型。
4.使用default为泛型类型变量指定初始值
有些算法,比如泛型集合List<T>的Find算法,所查找的对象有可能会是值类型,也有可能是引用类型。在这种算法内部,我们常常会为这些值类型变量或引用类型变量指定默认值。于是,问题来了:值类型变量的默认初始值是0值,而引用类型变量的默认初始值是null值,显然,这会导致下面的代码编译出错:
public T Func<T>() { T t=null; T t=0; return t; }
代码"T t=null;"在Visual Studio编译器中会警示: