《C#从现象到本质》读书笔记(七)第9章 泛型

《C#从现象到本质》读书笔记(七)第9章 泛型

泛型的三大好处:类型安全,增强性能(避免装箱和拆箱),代码复用。

泛型方法是传入的参数至少有一个类型为T(尚未制定的类型,根据微软的命名规则,通常以T开头)的方法。T称为类型参数。

它的使用契机一般为:传入类型可能有很多种、但处理方式却相同的情景。这是可以不需要写很多歌重载,而考虑用泛型方法达到代码复用的目的。

同名的泛型方法和非泛型方法会被编译器看做不同的方法。即使都是泛型方法,不同个数的类型参数也会被编译为不同的方法。

泛型约束使得类型参数只能是满足某些条件的类型。它分为如下几类:

1)接口约束。2)基类型约束。基类型约束必须放在其他约束之前。3)构造函数new()约束。new()约束出现在where子句的最后。

多个泛型类型参数,如where T:class where U:struct。

 1 class Program
 2 {
 3     static void Main(string[] args)
 4     {
 5         var r1 = new Rectangle(1, 6);
 6         var r2 = new Rectangle(2, 4);
 7         Compare(r1, r2, CompareRectangle);
 8 
 9         var c1 = new Cirtle(3);
10         var c2 = new Cirtle(2);
11         Compare(c1, c2, CompareCircle);
12 
13         Console.ReadKey();
14     }
15     public static int CompareRectangle(Rectangle r1, Rectangle r2)
16     {
17         double r1Area = r1.Length * r1.Width;
18         double r2Area = r2.Length * r2.Width;
19         if (r1Area > r2Area) return 1;
20         if (r1Area < r2Area) return -1;
21         return 0;
22     }
23     public static int CompareCircle(Cirtle c1, Cirtle c2)
24     {
25         if (c1.Radius > c2.Radius) return 1;
26         if (c1.Radius < c2.Radius) return -1;
27         return 0;
28     }
29     public static void Compare<T>(T o1, T o2, Func<T, T, int> rule)
30     {
31         var ret = rule.Invoke(o1, o2);
32         if (ret == 1) Console.WriteLine("第一个大");
33         if (ret == -1) Console.WriteLine("第二个大");
34         if (ret == 0) Console.WriteLine("一样大");
35     }
36 }
37 public struct Rectangle
38 {
39     public double Length { get; set; }
40     public double Width { get; set; }
41 
42     public Rectangle(double l, double w)
43             : this()
44     {
45         Length = l;
46         Width = w;
47     }
48 }
49 public struct Cirtle
50 {
51     public double Radius { get; set; }
52 
53     public Cirtle(double r)
54             : this()
55     {
56         Radius = r;
57     }
58 }

可变性是以一种类型安全的方式,将一个对象作为另一个对象来使用。可变性有两种类型:

1)协变。子类隐式转换为父类,若某方法声明返回类型为object,那么实际上它可以返回任何的类型。

2)逆变。父类隐式转换为子类。

“协变”->”和谐的变”->”很自然的变化”->string->object :协变。 

“逆变”->”逆常的变”->”不正常的变化”->object->string 逆变。

协变性和out关键字搭配使用,用于向调用者返回操作的值。接口中的T职能出现在输出中(包括方法的输出、属性的get访问器和委托的参数,因为委托支持协变),不能出现在输入中。

逆变性和in关键字搭配使用,此时类型出现在输入(包括方法的输入、属性的set访问器和委托的参数,因为委托支持逆变)。

协变和逆变体现在泛型类T和T的派生类。out和in关键字只能在接口和委托中使用,不支持泛型方法和泛型类。而且,值类型不参与协变和逆变。

C#中泛型可变性的限制:

1)只有接口和委托可以拥有可变的类型参数。in和out关键字只能用来修饰泛型接口和泛型委托。

2)可变性只能用于引用类型,禁止任何值类型之间的转换,以及值类型和引用类型之间的转换。

3)类型参数使用了out或者ref将禁止可变性。

4)不允许部分可变性。5)多播委托于可变性不能混用。

如果一个接口需要对T协变,那么这个接口所有方法的输入参数类型必须支持对T的逆变。如果接口要支持对T逆变,那么接口中方法的参数类型都必须支持对T协变。

原文地址:https://www.cnblogs.com/Lvkang/p/9718424.html