1.泛型的约束:
(1)接口约束;
(2)基类约束,基类约束必须放在第一(假如有多个约束);
(3)struct/class约束;
(4)多个参数类型的约束,每个类型参数都要用where关键字;
(5)构造器约束,只能是无参构造器,如new();
(6)约束可以由派生类继承,但必须在派生类中显式地指定这些约束;
(7)泛型方法的约束设置与泛型类的约束设置,是一样的;
2.协变性与逆变性:在泛型中,将一个较具体的类型赋给一个较泛化的类型,即是协变。将一个较泛化的类型赋给一个较具体的类型,即是逆变。
协变:在C#4.0中使用out类型参数修饰符允许协变性,该out修饰的类型参数,会导致该类型参数只能用于成员的返回与属性的取值方法,永远不用于输入参数或者属性的赋值方法。
逆变:在C#4.0中使用in类型参数修饰符允许逆变性,该in修饰的类型参数,会导致该类型参数只能用于成员的输入(输入参数)与属性的设置方法。
如Contact类继承自PdaItem,若对泛型接口(IConvertible<in T1,out T2>)进行了协变与逆变的设置,就可以成功地从一个IConvertible<PdaItem,Contact>转换成一个IConvertible<Contact,PdaItem>。
综上所述:协出逆进。
3.数组本身是支持协变与逆变,如PdaItem[] pdaItems=new Contact[]{},Contact[] pdaItems=(Contact)new PdaItem[]{}。
4.委托概述:长期以来经验丰富的C、C++程序员利用方法指针,,将可执行的步骤(方法)作为参数传递给另一个方法。C#使用委托来提供相同的功能,它将方法作为对象封装起来,允许在运行时间接绑定一个方法的调用,可查看DelegateSample类的代码。
5.委托的定义:C#将所有委托的定义成间接派生于System.Delegate,其继承层次为Object -> Delegate ->MulticastDelegate -> 自定义委托。当然我们使用关键delegate声明,其在编译后生成的CIL代码,就是自动继承上面的结构,因此我们不能手动显式继承委托。在委托实例化中,从C@2.0开始可以不使用new来手工创建,直接赋值相同的签名方法即可,编译器会在编译过程中会自动根据委托推断,自动添加new创建,以及把方法名称作为委托参数传递也是一样,
6.系统自定义的委托:在.net3.5(C#3.0)中加入了Action与Func这个两个泛型委托,前者是没有返回值的委托,后者是有返回值的委托,在.Net4.0(C#4.0)中又在这些泛型委托中加入了in(逆变)/out(协变)的功能。这些委托的定义省略了我们手工进行自定义委托的情况,因为这些泛型委托都涵盖了我们可能遇到的所有使用情况。(除非你要定义一个有特殊含义的委托名称)。
7.委托使用可变性,即委托类型参数的可变性(协变与逆变),可查看DelegateSample.CovariantAndContravariant()方法的代码。
8.Lambda表达式:Lambda表达式是匿名函数的简洁表达形式,Lambda表达式包含语句Lambda与表达式Lambda,前者可以含有多个语句的语句块(一般只使用两三条语句),后者只有一句表达式。
9.使用Lambda表达式注意事项:
(1)Lambda表达式本身是无类型,只有赋值给一个委托,Lambda表达式就表现为有一个类型,就是该方法签名的委托。
(2)因Lambda表达式是无类型的,所以也就不能赋值给隐式类型的局部变量。
(3)如果目的地在Lambda表达式的外部,C#就不允许在匿名函数内部使用跳转语句(break、goto、continue),类似的,不能从Lambda表达式外部跳入Lambda表达式内部。
(4)对于在Lambda表达式内部引入的变量,其作用域仅限于Lambda表达式主体。
(5)编译器的程序执行流程分析机制检测不到在Lambda表达式内部初始化局部变量的情况。
以上的注意事项的代码实例,可以查看DelegateSample.NoticeMatter()方法。
10.Lambda表达式并非CLR内部的固有构造,它们的实现是由C#编译器在编译时生成的,编译器会自动把Lambda表达式生成为一个当前类的内部方法(静态或实例方法),其方法名是编译器自动处理(其一般含有anonymous等字眼的描述)。
11.在匿名函数中使用外部局部变量,编译器会把这些外部变量生成为当前类的嵌套类(sealed闭包)的公共字段,其嵌套类中含有公共字段与对应的匿名名称方法,因此这些局部变量变成了嵌套的成员,其生命周期也就被延长了。通过查看ILdasm(中间语言反编译,能够查看类库编译后的中间语言,VS工具自带)。也可查看DelegateSample.AscendingAndTimeOfCompiler()与_LocalDisplayClass_00001嵌套类。