c#泛型

泛型

一.泛型的作用

跨类型可复用的代码:继承 和 泛型.

继承 => 基类

泛型 => 带有"(类型)占位符"的"模板"

二.泛型类型

泛型会声明类型参数-泛型的消费者需要提欧共类型参数来把占位符类型填充上.

// 泛型类
public class Stack<T>{
    int position;
    T[] data = new T[100];
    public void Push(T ojb) => data[poisition++] = ojb;
    public T Pop() => data[--poistion]
}
// 使用泛型
Stack<int> stack = new Stack<int>();
stack.Push(12);   // poistion = 1
stack.Push(15);   // poistion = 2
int x = stack.Pop(); // poisiton = 1 ,data[1] x = 2;
int y = stack.Pop(); // y = 1
// 推导
public class ###{
    int position;
    int  data = new int[100];
    public void Push(int ojb) => data[poisition++] = ojb;
    public int Pop() => data[--poistion]
}

OPEN TYPE & CLOSE TYPE

Stack Open Type(开发类型)

Stack Close Type(封闭类型)

在运行时,所有的泛型类型实际都是封闭的(占位符类型已经被填充了)

var stack = new Stack<T>(); // 异常!
// 下面是允许的
public class Stack<T>{
    ...
    public Stack<T> Clone(){
        Stack<T> clone = new Stack<T>();
        ...
    }
}

泛型为什么会出现

public class Stack{
    int position;
   	object data = new object[100];
    public void Push(object ojb) => data[poisition++] = ojb;
    public object Pop() => data[--poistion]
}

需要装箱子和向下转换,这种转换在编译时无法进行检查

stack.Push("s"); // 装箱
int i = (int)stack.Pop(); // 无法向下转换报错!!!

三.泛型方法

泛型方法在方法的签名内也可以声明类型参数

// 泛型方法
static void Swap<T>(ref T a,ref T b){
    T temp = a;
    a = b;
    b = temp;
}
// 调用
int a = 2;
int b = 3;
Swap(ref a,ref b);
Console.WriteLine($"{a},{b}"); // a=3 b=2

在泛型类型里面的方法,除非也引入了类型参数T ,否则是不会归为泛型方法的

public class Stack<T>{
    int position;
    T[] data = new T[100];
    public void Push(T ojb) => data[poisition++] = ojb;
    public T Pop() => data[--poistion]  //这个不是泛型方法
}

只有类型和方法可以引入类型参数,属性,索引器,事件,字段,构造函数,操作符等都不可以声明类型参数,但是他们可以使用他们所在的泛型类型的类型参数.

四.声明类型参数

在声明class,struct,interface,delegated的时候可以引入类型参数.

其他的例如属性,就不可以引入类型参数,但是可以使用类型参数

public struct Nullable<T>{
    public T Value{get;;}
}

泛型类型/泛型方法也可有多个类型参数

class Dictionary<Tkey,Tvalue>{....};

Dictionary<int,stirng> myDic = new Dictionary}<int, string>();

var myDic = new Dictionary}<int, string>();

泛型类型/泛型方法的名称可以被重载,条件是参数类型的个数不同

class A{}
class A<T> {}
class A<T1,T2>{}

// 按照约定,泛型类型/泛型方法如果只有一个类型参数,那么就叫T
// 当使用多个类型参数的时候,每个类型参数都使用T作为前缀,随后跟着具体的描述性的名字

typeof与未绑定的泛型类型

开发的泛型类型在编译后就编程了封闭的泛型类型

但是如果作为Type对象,那么为绑定的泛型类在运行时是可以存在的. 只能通过typeof操作符来实现

class A<T>{}
class A<T1,T2>{}

Type a1 = typeof(A<>);
Type a2 = typeof(A<,>);
Type a3 = typeof (A<int,int>);
class B<T>{void X(){Type t = typeof(T);}}

五.泛型的默认值

使用default关键字来获取泛型类型参数的默认值

static void Zap<T>(T[] array){
    for(int i =0;i<array.Length;i++){
        array[i] = default(T) // t是引用类型那么是null t是值类型是0
    }
}

六.泛型的约束

默认情况下,泛型的类型参数可以是任何类的类型

如果只允许使用特定的类型参数,就可以指定约束

where T :struct 		// 类型T必须是值类型
where T :class 			// T必须是引用类型
where T :IFoo 			// T必须实现接口IFoo
where T :Foo 			// T必须派生自基类Foo
where T :new() 			// 指定类型T必须有个一默认构造函数
where T :T2 			// 类型T派生自泛型类型T2
public class MyClass<T> where T:new(){
    ...
}
class SomeClass{}
interface Interface1{}

class GenericaClass<T,U> where T: SomeClass,Interface1  // 必须继承SomeClass 且 实现 Interface接口
    					 where U:new() // 必须有个构造函数
{...}

泛型类型的子类

泛型class可以有子类,在子类里,可以继续让父类的类型参数保持开放

class Stack<T>{...}
class SpecialStack<T>:Stack<T>

在子类李,也可以使用具体的类型来关闭(封闭)父类的类型参数

class IntStack:Stack<int>{...}

子类型也可以引入新的类型参数

class List<T>{...}
class KeyedList<T,Tkey>:List<T>

自引用的泛型类型

在封闭类型参数的时候,改类型可以把他自己作为具体的类型

public interface IEquatable<T> {bool Equals(T obj);}

public class Balloon:IEquatable<Balloon>{
    ...
    public bool Equals(Balloon b){
        if(b==null)return false;
        return true;
    }
}

静态数据

针对每一个封闭类型,静态数据是唯一的

class Bob<T> { public static int Count; }

static class Test
{
    public static void  set_bob()
    {
        Console.WriteLine(++Bob<int>.Count); //1
        Console.WriteLine(++Bob<int>.Count); //2
        Console.WriteLine(++Bob<string>.Count); //1
        Console.WriteLine(++Bob<object>.Count); //1
    }
}

类型参数转换

  • c#的类型操作符支持下列转换
    • 数值转换
    • 引用转换
    • 装箱拆箱转换
    • 自定义转换
  • 决定采用的是那种转换,发生在编译时,根据已知类型的操作数来决定
public StringBuilder foo<T>(T arg){
    StringBuilder sb = arg as StringBuilder;
    .....
}
吾虽浪迹,却未迷失本心
原文地址:https://www.cnblogs.com/lddragon1/p/15545570.html