泛型
泛型的作用
跨类型可复用的代码:继承和泛型
继承 => 基类
泛型 =>带有"(类型)占位符"的"模板"
泛型类型(GENERICTYPES)
泛型会声明类型参数 — 泛型的消费者需要提供类型参数(argument) 来把占位符类型填充上.
public class Stack
{
int position;
T[] data = new T[100];
public void Push(T obj) => data[position++] = obj;
public T Pop() => data[–position];
}
var stack = new Stack();
stack.Push(5);
stack.Push(10);
int x = stack.Pop();
int y = stack.Pop();
public class
{
int position;
int [] data = new int[100];
public void Push(int obj) => data[position++] = obj;
public int Pop() => data[–position];
}
开放类型和封闭类型
StackOpen Type(开放类型)
StackClosed Type(封闭类型)
在运行时,所有的泛型类型实例都是封闭的(占位符类型已被填充了)
var stack = new Stack();
public class Stack
{
public Stack clone = new Stack();
}
泛型为何会出现?
public class ObjectStack
{
int position;
object[] data = new object[10];
public void Push (object obj) => data[position++] = obj;
public object Pop() =>data[–position];
}
需要装箱和向下转换,这种转换在编译时无法进行检查
stack.Push(“s”);
int i = (int)stack.Pop();
泛型方法
static void Swap(ref T a,ref T b)
{
T temp = a;
a = b;
b = temp;
}
int x = 10;
int y = 10;
Swap(ref x, ref y);
泛型方法
在泛型类型里面的方法,除非也引入了类型参数,否则是不会归为泛型方法的.
只有类型和方法可以引入类型参数,属性,索引器,事件,字段,构造函数,操作符等都不可以声明类型参数.但是他们可以使用他们所在的泛型类型的类型参数
public T this [int index] => data[index];
public Stack(){}
声明类型参数
在声明class,struct,interface,delegate的时候可以引入类型参数
其他的例如属性,就不可以引入类型参数,但是可以使用类型参数.
public struct Nullable
{
public T Value{get;}
}
泛型类型/泛型方法可以有多个类型参数:
声明泛型类型
泛型类型/泛型方法的名称可以被重载,条件是参数类型的个数不同:
class A{}
class A{}
class A <T1,T2>{}
按约定,泛型类型/泛型方法如果只有一个类型参数,那么就叫T
当使用多个类型参数的时候,每个类型参数都使用T作为前缀,随后跟着具有描述性的名字.
Typeof与未绑定的泛型类型
开放的泛型类型在编译后就变成了封闭的泛型类型.
但是如果作为Type对象,那么未绑定的泛型类型在运行时是可以存在的.
(只能通过typeof操作反来实现)
class A{}
class A <T1,T2>{}
Type a1 = typeof(A<>);
Type a2 = typeof(A<,>);
泛型的默认值
使用default关键字来获取泛型类型参数的默认值
static void Zap(T[] array)
{
for (int i = 0;i < array.Length; i++)
array[i] = default(T);
}