zoukankan      html  css  js  c++  java
  • 详解C#泛型(二)

      一、自定义泛型方法(Generic Method),将类型参数用作参数列表或返回值的类型:

    void MyFunc<T>() //声明具有一个类型参数的泛型方法
    {
        Type genericType = typeof(T); //在泛型方法体内部获取类型参数的类型信息
        //do…
    }
    //调用泛型方法
    MyFunc<int>();

      1.声明泛型方法时,可以在参数列表中使用这个类型参数:void MyFunc<T>(T obj) { };此时在调用该泛型方法时可以省略类型参数的指定由编译器推断其类型,例如:MyFunc<int>(myNum)与MyFunc(myNum)完全等效;

      2.声明泛型方法时,可以在返回值类型中使用这个类型参数:T MyFunc<T>() { return default(T); };编译器的类型推断功能不适用于仅在返回值类型中使用类型参数的情况,此种情况在调用时必须显式指定类型参数;

      3.声明泛型方法时,方法的参数列表和返回值可以指定相同或不相同的类型参数,如果不相同则一般参数列表的类型参数在前,返回值的类型参数在后:U MyFunc<T, U>(T obj) { return default(U); },此时依然不能使用编译器的类型推断功能;如果相同,则在调用时可以使用编译器的类型推断功能省略类型参数的显式指定;
    类型参数数量的不同,可以构成重载方法:

    void MyFunc() { }
    void MyFunc<T>() { }
    void MyFunc<T, U>() { }

      4.泛型方法中的类型参数也可以指定约束;

      5.在泛型类中声明的方法,方法的参数列表和返回值可以使用泛型类的类型参数作为类型;泛型方法可出现在泛型或具体类型中,只有当方法有属于自己的类型参数时才是泛型方法,在泛型类中声明泛型方法时,二者类型参数的占位符不可以相同:

    class MyClass<T> //声明一个泛型类,类型参数占位符为T
    {
        void MyFunc(T obj) //声明一个非泛型方法,使用泛型类的类型参数T作为参数类型
        {
            //do…
        }
        //不能声明泛型方法void MyFunc<T>,泛型方法的类型参数占位符不能与类的类型参数占位符相同
        void MyFunc<U>(T obj1, U obj2) //声明一个泛型方法,类型参数占位符为U
        {
            //do…
        }
    }
    class MyClass //定义一个具体类
    {
        void MyFunc<T>(T obj) //声明一个泛型方法
        {
            //do…
        }
    }            

       二、自定义泛型接口(Generic Interface),将类型参数用作参数列表或返回值的类型:

    interface IMyInterface<T> //定义具有一个类型参数的泛型接口
    {
        void MyFunc(T obj); //声明参数为T的方法
    }
    //声明泛型类继承自泛型接口
    public class MyClass<T> : IMyInterface<T>
    {
        public void MyFunc(T obj)
        {
            //do…
        }
    }
    //指定类型参数为string类型,创角泛型类的实例赋值给泛型接口的变量
    IMyInterface<string> iMyInterface = new MyClass<string>();

      1.适用于泛型类的规则基本也适用于泛型接口;

      三、自定义泛型委托(Generic Delegate),将类型参数用作参数列表或返回值的类型:

    delegate void MyDelegate<T>(T obj); //定义具有一个类型参数的泛型委托,参数列表中有一个参数
    void MyGenericFunc<T>(T obj) //声明一个泛型方法,参数列表中有一个参数
    {
        //do…
    }
    void MyFunc(string str)
    {
        //do…
    }
    //声明泛型委托的实例,指定类型参数为string类型,此时可匹配的方法签名为void myFunc(string str)
    MyDelegate<string> myDelegate;
    //赋值一个指定类型参数为string的泛型方法
    myDelegate = MyGenericFunc<string>;
    //添加一个参数列表为string类型的具体方法
    myDelegate += MyFunc;

      1.泛型委托同泛型类一样,需要在实例化时指定类型参数的类型;

      2.泛型委托的实例同具体委托的实例一样,只需要方法的参数列表和返回值类型相同即可进行匹配,因此不管目标方法是指定了符合要求类型的泛型方法还是具体方法都可以进行匹配; 

      四、反射中的泛型:

    Type myType = typeof(MyClass<>); //获取未指定任何类型参数的开放式构造类的类型信息,多个类型参数时添加,:typeof(MyClass<,>)
    myType = myType.MakeGenericType(typeof(int)); //通过类型信息的实例方法MakeGenericType()构建指定所有类型参数的封闭式构造类的类型信息,如未指定所有类型参数会抛出异常ArgumentException
    //也可以直接获取封闭式构造类的类型信息,当类型参数在一开始就确定时推荐使用此种方式
    //myType = typeof(MyClass<int>); //多个类型参数时需要同时指定:typeof(MyClass<int, string>)

      1.通过反射只可以获取未指定任何类型参数的开放式构造类的类型信息和指定所有类型参数的封闭式构造类的类型信息,即无法获取MyClass<int, >的类型信息;


    如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的认可是我写作的最大动力!

    作者:Minotauros
    出处:https://www.cnblogs.com/minotauros/

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    [APIO2012]派遣
    Luogu_2774 方格取数问题
    Luogu4149 [IOI2011]Race
    Luogu_4886 快递员
    Loj_6282. 数列分块入门 6
    LOJ 6281 数列分块入门 5
    三维偏序 cdq
    【逆序对】 模板
    【luogu P1637 三元上升子序列】 题解
    【luogu P3609 [USACO17JAN]Hoof, Paper, Scissor蹄子剪刀布】 题解
  • 原文地址:https://www.cnblogs.com/minotauros/p/9965997.html
Copyright © 2011-2022 走看看