目录
C#中的泛型
泛型允许我们声明 类型参数化 的代码,可以用不同的类型进行实例化
C#提供了5钟泛型:类,结构,接口,委托和方法 前面四个是类型,而方法是成员
↑ 这张图看不懂什么意思
泛型类
泛型类不是实际的类,而是类的模板,所以我们必须先从他们构建实际的类类型,然后创建这个构建后的类类型的实例
声明泛型类
创建构造函数
创建变量和实例
类型参数的约束
要让泛型变得更有用,我们需要提供额外的信息让编译器直到参数可以接受那些类型。这些额外的信息叫做约束。只有符合约束的类型才能替代给定的类型参数,来产生构造函数
Where 子句
约束使用where子句列出
泛型方法
方法是成员不是类型,泛型方法可以在泛型和非泛型类以及结构和接口中声明
声明泛型方法
调用泛型方法
扩展方法和泛型类
- using System;
- using System.Collections.Generic;
- using System.Text;
-
- namespace Csharpzuoye
- {
-
- static class ExtendHolder
- {
- public static void Print<T>(this Holder<T> h)
- {
- T[] vals = h.GetValues();
- Console.WriteLine("{0},\t{1},\t{2}", vals[0], vals[1], vals[2]);
- }
- }
- class Holder<T>
- {
- T[] vals = new T[3];
-
- public Holder(T v0,T v1,T v2)
- { vals[0] = v0; vals[1] = v1; vals[2] = v2; }
-
- public T[] GetValues() { return vals; }
- }
-
- class Program
- {
- static void Main()
- {
- var intHolder = new Holder<int>(3, 5, 7);
- var stringHolder = new Holder<string>("a1", "b2", "c3");
- intHolder.Print();
- stringHolder.Print();
- }
- }
- }
泛型结构
与泛型类相似,泛型结构可以有类型参数和约束。泛型结构的规则和条件与泛型类是一样的
泛型委托
类型参数决定了能接受什么样的方法
泛型接口
泛型接口允许我们编写参数和接口成员返回类型是泛型类型参数的接口。
- using System;
- using System.Collections.Generic;
- using System.Text;
-
- namespace Csharpzuoye
- {
- interface IMyIfc<T>
- {
- T ReturnIt(T invalue);
- }
-
- class Simple<S>: IMyIfc<S>
- {
- public S ReturnIt(S invalue)
- { return invalue; }
- }
-
-
- class Program
- {
- static void Main()
- {
- var trivInt = new Simple<int>();
- var trivString = new Simple<string>();
-
- Console.WriteLine("{0}", trivInt.ReturnIt(5));
- Console.WriteLine("{0}", trivString.ReturnIt("Hi,there."));
- }
- }
- }
实现泛型类型接口时,必须保证类型参数组合不会在类型中产生两个重复的接口
协变
可变性: 协变,逆变,不变
每一个变量都有一种类型,你可以将派生类对象的实例赋值给基类的变量,这叫做赋值兼容性
其中Dog 是 Animal的派生类,但是对于Animal的委托不接受Dog的引用,虽然Dog的引用也等于Animal的引用
如果派生类只是用于输出值,那么这种结构化的委托有效性之间的常数关系叫做协变。为了让编译器知道这是我们的期望,必须使用out关键字标记委托声明中的类型参数
逆变
接口的协变和逆变