c# 泛型

泛型用符号“T”来定义。“T”代表 任意合法的类型。书中通常称之为泛型类型。 对这个T(任意类型)的限定,赋予其它功能。构成了泛型的主要内容和难点。

一、泛型基本定义

1、泛型类

public class MyClass<T>{}

2、泛型接口

public interface ImyInterface<T>{}

3、泛型结构

public struct MyStruct<T>{}

4、泛型方法.可以在非泛型类中定义

void Swap<T>(){}

二、约束 对T的限定

public class DocumentManager<T>
     where T: IDocument   //说明T这个任意类型,继承了IDocument 接口。这样可以把documentQueue集合中所有实现了IDocument接口的对象,赋值给IDocument 接口变量。(多态)

public void DisplayAllDocuments()
    {
      foreach (T doc in documentQueue)
      {
        Console.WriteLine(doc.Title); //这条语句其实是 Console.WriteLine((IDocument)doc.Title); 将doc强制转为IDocument类型。 编译器支持语法糖。可以不用写这个了。
} }

三、协变 逆变

1. 仅有泛型接口和泛型委托支持对类型参数的可变性,泛型类或泛型方法是不支持的。

2. 值类型不参与协变或反变,IFoo<int>永远无法变成IFoo<object>,不管有无声明out。因为.NET泛型,每个值类型会生成专属的封闭构造类型,与引用类型版本不兼容。

3. 声明属性时要注意,可读写的属性会将类型同时用于参数和返回值。因此只有只读属性才允许使用out类型参数,只写属性能够使用in参数。

Rectangle继承与Shape
 static void Main()
    {
      IIndex<Rectangle> rectangles = RectangleCollection.GetRectangles();//创建了一个新的对象
      IIndex<Shape> shapes = rectangles;  //子泛型接口 赋值给 父泛型接口

      for (int i = 0; i < shapes.Count; i++)
      {
        Console.WriteLine(shapes[i]);
      }


      IDisplay<Shape> shapeDisplay = new ShapeDisplay();//创建一个对象,这个对象需要传递一个shape对象,用于显示
      IDisplay<Rectangle> rectangleDisplay = shapeDisplay; // 父泛型接口 赋值给 子泛型接口 传递一个tectangle对象也当然可以了 
      rectangleDisplay.Show(rectangles[0]);
      Console.ReadKey();
    }

子类可以变为父类,子泛型接口也可以变为父泛型接口,称之为协变的泛型接口(无此概念,但可以这么理解)(主要指 返回值) 

父类不可以变为子类(一般情况),但子泛型接口却可以赋值给父泛型接口,称之为逆变的泛型接口。(主要指 参数)

协变和逆变,更加抽象,可以建立更加抽象的模型和软件架构。但是用起来的时候,规则较多。在计算机编程领域并不是一个好的方法和逻辑。应该抛弃,用另一种更加抽象的逻辑来替代,个人建议不用学习这个语法。不符合思维本性。思维本身应该是不断的归类,简化才对。觉得抽象出泛型就可以了,再往上,就有点复杂了。也没有必要。面向对象编程,已经是对自然的一种契合。不能再走入过去的路子了。编程语言应该贴近思维习惯,贴近人类经验的框架才对。不满足的全部应该淘汰。

原文地址:https://www.cnblogs.com/crhdyl/p/4929788.html