CLR Via CSharp读书笔记(12):泛型

CLR允许创建 generic reference types 以及generic value types, 但是不允许创建 generic enumerated types.

代码爆炸
当一个使用泛型参数的方法被JIT编译时,CLR取出方法的中间语言(IL),替换指定的类型参数然后创建操作指定数据类型的方法的本地代码。CLR持续产生针对不同方法/数据类型组合的本地代码,这被称为代码爆炸。

CLR有一些内建的优化器用以减少代码爆炸:
首先,同一个AppDomain中不同的程序集均使用List<DateTime>, CLR仅会编译一次List<DateTime>。
其次,CLR认为所有的引用类型都是等同的,因此,为使用List<String>参数的方法编译的代码,可以被使用List<Stream>参数的方法使用,因为所有引用类型参数事实上是指向位于堆上的对象的指针。所有针对指针的操作方法都一样。
但是,如果类型参数是值类型CLR必须为该值类型生成指定的本地代码,因为不同的CPU指令被用于操作这些值类型,即使他们有相同的大小(size)。

委托事实上就是有如下四个方法的一个类定义:构造函数,Invoke方法,BeginInvoke方法和EndInvoke方法。

 如果像下面这样定义了一个泛型委托:

public delegate TReturn CallMe<TReturn, TKey, TValue>(TKey key, TValue value);

编译器将其转换为类似于如下的一个类:

public sealed class CallMe<TReturn, TKey, TValue>
{
    public CallMe(Object obj, IntPtr method);
    public virtual TReturn Invoke(TKey key, TValue value);
    public virtual IAsyncResult BeginInvoke(TKey key, TValue value, AsyncCallback callback, Object obj);
    public virtual TReturn EndInvoke(IAsyncResult result);
}

主限制(primary constraint) -- zero or one

引用类型(class)
internal
sealed class PrimaryConstraintOfClass<T> where T : class { public void M() { T temp = null;// Allowed because T must be a reference type } }
值类型(struct):
internal sealed class PrimaryConstraintOfStruct<T> where T : struct { public static T Factory() { // Allowed because all value types implicitly // have a public, parameterless constructor return new T(); } }

辅助限制(secondary constraint) -- zero or more

 接口类型限制以及嵌套类型限制

private static List<TBase> ConvertIList<T, TBase>(IList<T> list)
    where T : TBase
{
    List<TBase> baseList = new List<TBase>(list.Count);
    for (Int32 index = 0; index < list.Count; index++)
    {
        baseList.Add(list[index]);
    }
    return baseList;
}

构造函数限制(constructor constraint) -- zero or one

internal sealed class ConstructorConstraint<T> where T : new()
{
    public static T Factory()
    {
        // Allowed because all value types implicitly
        // have a public, parameterless constructor and because
        // the constraint requires that any specified reference
        // type also have a public, parameterless constructor
        return new T();
    }
}

泛型类型和继承

internal sealed class Node<T>
{
    public T m_data;
    public Node<T> m_next;

    public Node(T data) : this(data, null){
    }
    public Node(T data, Node<T> next){
        m_data = data; 
        m_next = next;
    }
}

private static void SameDataLinkedList()
{
    Node<Char> head = new Node<Char>('C');
    head = new Node<Char>('B', head);
    head = new Node<Char>('A', head); // 'A' 必须与'B'类型相同
    Console.WriteLine(head.ToString());
}

更好的方法:

internal class Node
{
    protected Node m_next;
    public Node(Node next){
        m_next = next;
    }
}
internal sealed class TypedNode<T> : Node
{
    public T m_data;
public TypedNode(T data) : this(data, null){ } public TypedNode(T data, Node next) : base(next){ m_data = data; } }

private static void DifferentDataLinkedList(){
    Node head = new TypedNode<Char>('.');
    head = new TypedNode<DateTime>(DateTime.Now, head);
    head = new TypedNode<String>("Today is ", head); // 'Today is' 可以与DateTime.Now类型不同
    Console.WriteLine(head.ToString());
}



原文地址:https://www.cnblogs.com/thlzhf/p/2805438.html