泛型
泛型概述
- 性能
- 值类型存储在栈上,引用类型存储在堆上。
- C#类是引用类型,结构是值类型。.NET容易把值类型换成引用类型:装箱和拆箱
- 装箱和拆箱对于性能的损耗很大
- 类型安全性
- 二进制代码的重用
- 代码的扩展
- 命名约定
- 泛型类型的名字用字母T作为前缀
- 如果没有特殊的要求,泛型类型允许用任意类替代。且只是用了一个泛型类型,就可以用字母T作为单行类型的名称
public class List<T> { } public class LinkedList<T> { }
- 如果泛型类型有特殊的要求(例如:他必须实现一个接口或派生自基类),或者使用了两个或多个泛型类型,就应给泛型类型使用描述性的名称
创建泛型类
public class MyGenericArray<T> // 泛型:T { private T[] array; public MyGenericArray(int size) { array = new T[size + 1]; } public T getItem(int index) { return array[index]; } public void setItem(int index, T value) { array[index] = value; } }
泛型类的功能
- 默认值
- 约束
约束 | 说明 |
where T :struct | 对于结构约束,类型T必须是值类型 |
where T : class | 类约束指定类型T必须是引用类型 |
where T : IFoo | 指定类型T必须实现接口IFoo |
where T : Foo | 指定类型T必须派生自基类Foo |
where T : new() | 这是一个构造函数的约束,必须有一个默认的构造函数 |
where T : T2 | 类型T派生自泛型T2 |
- 继承
- 静态成员
public class StaticDemo<T> { public static int x; } StaticDemo<string>.x = 1; StaticDemo<int>.x = 2; Console.WriteLine(StaticDemo<string>.x); // 1 Console.WriteLine(StaticDemo<int>.x); // 2
泛型接口
- 协变和抗变:类型转化的问题
泛型结构
- ? 号:可空类型修饰符
引用类型可以使用空引用表示一个不存在的值,而值类型通常不能表示为空。例如:string str=null; 是正确的,int i=null; 编译器就会报错。为了使值类型也可为空,就可以使用可空类型,即用可空类型修饰符"?"来表示,表现形式为"T?"例如:int? 表示可空的整形,DateTime? 表示可为空的时间。T? 其实是System.Nullable(泛型结构)的缩写形式,也就意味着当你用到 T?时编译器编译时会把 T?编译成System.Nullable的形式。例如:int?,编译后便是System.Nullable的形式。
泛型方法
- Swap(ref int x, ref int y)
void Swap<T>(ref T x, ref T y) { T temp; temp = x; x = y; y = temp; }