CLR via C#学习笔记-第十二章-泛型方法和其他成员

12.6 泛型方法

方法和类可以各自定义类型参数

定义泛型类、结构或接口时,类型中定义的任何方法都可以引用类型指定的类型参数。

类型参数可以作为方法参数、返回值或方法内部定义的局部变量的类型使用。

CLR还允许方法指定他自己的类型参数,这些参数也可以作为参数、返回值或局部变量的类型使用。

在下例中类型定义了一个类型参数,方法也定义了自己的:

internal sealed class GenericType<T>{
    private T m_value;
    public GenericType(T value){m_value=value;}
    public TOutput Converter<TOutput>(){
        TOutput result=(TOutput)Converter.ChangeType(m_value,typeof(TOutput);
        return result;
    }
}

Converter方法将字段引用的对象转换成任意类型——具体取决于调用时传递的类型实参是什么。

泛型方法的调用

泛型方法的一个很好的例子是Swap方法:

private static void Swap<T>(ref T o1,ref T o2){
    T temp=o1;
    o1=o2;
    o2=temp;
}

现在可以这样调用Swap:

private static void CallingSwap(){
    Int32 n1=1;n2=2;
    Swap<Int32>(ref n1,re n2);
    String s1="A",s2="B";
    Swap<String>(ref s1,ref s2);
}

为获取out和ref参数的方法使用泛型类型很有意思,

因为作为out/ref实参传递的变量必需具有与方法参数相同的类型,以免损害类型安全性。

涉及out/ref参数的这个问题在9.3节已作讨论。

泛型方法和类型推断

C#编译器支持在调用泛型方法是进行类型托短,增强可读性、维护性:

private static void CallingSwap(){
    Int32 n1=1;n2=2;
    Swap(ref n1,re n2);
    String s1="A";
    Object s2="B";
    Swap(ref s1,ref s2);//错误,不能推断
}

即使s2是Object,即使他恰好引用一个String,由于s1,s2是不同的数据类型的变量,编译器拿不准腰围Swap传递什么类型实参,所以会报错。

方法重载为泛型

类型可以定义多个方法,让其中一个方法接受具体数据类型,另一个接受泛型参数,如下所示:

private static void Display(String s){
    Console.WriteLine(s);
}
private static void Display(T o){
    Display(o.ToString());
}

下面展示了调用Display方法的一些方式:

Display("Jeff");//调用Display(String)
Display(123);//调用Display<T>(T)
Display<String>("Aidan");//调用Display<T>(T)

在第一个调研中,编译器可以接受第一个String参数的方法也可以接受泛型Display方法。

但C#编译器的策略是先考虑明确的匹配再考虑泛型匹配。否则会造成无限递归。

12.7 泛型和其他成员

在C#中,属性、索引器、时间、操作符方法、构造器和终结器本身不能有类型参数,但它们能在泛型类型中定义。

之所以不允许他们指定自己的泛型类型参数,是因为微软开发人员认为没有必要,而且为这些成员添加泛型支持的代价是相当高的。

原文地址:https://www.cnblogs.com/errornull/p/9902703.html