19、泛型

1. 简介:

2.0 版 C# 语言和公共语言运行时 (CLR) 中增加了泛型。 泛型将类型参数的概念引入 .NET Framework,类型参数使得设计如下类和方法成为可能:这些类和方法将一个或多个类型的指定推迟到客户端代码声明并实例化该类或方法的时候。

2. 语法:

    class ClassName<Type>
    {
         public void Add(Type input)
        {
        }
    }

    class Program
    {
        public void test0()
        {
            ClassName<int> testClass = new ClassName<int>();
            testClass.Add(5);
            print<int>(5, 6);
            print(5, 6); // <>可以省略
        }

        public void print<T1>(T1 x, T1 y)
        {
            Console.WriteLine(x.ToString(),y.ToString());
        }

    }

3. 约束:

1> 约束简介

在定义泛型类时,可以对客户端代码能够在实例化类时用于类型参数的类型种类施加限制。 如果客户端代码尝试使用某个约束所不允许的类型来实例化类,则会产生编译时错误。 这些限制称为约束。 约束是使用 where上下文关键字指定的。 下表列出了六种类型的约束:

约束 说明
T : struct 类型参数必须是值类型。
T : class 类型参数必须是引用类型;这一点也适用于任何类、接口、委托或数组类型。
T:new() 类型参数必须具有无参数的public构造函数。 当与其他约束一起使用时,new() 约束必须最后指定。
T:<基类名> 类型参数必须是指定的基类或派生自指定的基类。
T:<接口名称> 类型参数必须是指定的接口或实现指定的接口。 可以指定多个接口约束。 约束接口也可以是泛型的。
T:U 为 T 提供的类型参数必须是为 U 提供的参数或派生自为 U 提供的参数。
2> 约束简介案例
    class TestClass<TestType> where TestType : struct
    {
            
    }

    static void Main(string[] args)
     {
            TestClass<int> t1 = new TestClass<int>();

            //TestClass<string> t2 = new TestClass<string>(); 错误,只能传递值类型
    }
3> 使用泛型约束的原因(优势)

如果要检查泛型列表中的某个项以确定它是否有效,或者将它与其他某个项进行比较,则编译器必须在一定程度上保证它需要调用的运算符或方法将受到客户端代码可能指定的任何类型参数的支持。 这种保证是通过对泛型类定义应用一个或多个约束获得的。 例如,基类约束告诉编译器:仅此类型的对象或从此类型派生的对象才可用作类型参数。 一旦编译器有了这个保证,它就能够允许在泛型类中调用该类型的方法。

可以对同一类型参数应用多个约束,并且约束自身可以是泛型类型,如下所示:

        class EmployeeList<T> where T : Employee, IEmployee, System.IComparable<T>, new()
        {
            // ...
        }
4> 泛型约束的注意点:

通过约束类型参数,可以增加约束类型及其继承层次结构中的所有类型所支持的允许操作和方法调用的数量。 因此,在设计泛型类或方法时,如果要对泛型成员执行除简单赋值之外的任何操作或用 System.Object不支持的任何方法,您将需要对该类型参数应用约束。在应用 where T : class 约束时,避免对类型参数使用 == 和 != 运算符,因为这些运算符仅测试引用同一性而不测试值相等性。

5> 约束多个参数

可以对多个参数应用约束,并对一个参数应用多个约束,如下面的示例所示

         class Base { }
         class Test<T, U>
            where U : struct
            where T : Base, new()
            { }
6> 未绑定的类型参数

没有约束的类型参数(如公共类 SampleClass<T>{}中的 T)称为未绑定的类型参数。 未绑定的类型参数具有以下规则:

  • 不能使用 !=和 == 运算符,因为无法保证具体类型参数能支持这些运算符。

  • 可以在它们与 System.Object之间来回转换,或将它们显式转换为任何接口类型。

  • 可以将它们与 [null] 进行比较。 将未绑定的参数与 null进行比较时,如果类型参数为值类型,则该比较将始终返回 false。

7> 作为约束的类型参数

将泛型类型参数作为约束使用,在具有自己类型参数的成员函数必须将该参数约束为包含类型的类型参数时非常有用,如下示例所示:

        class List<T>
        {
            void Add<U>(List<U> items) where U : T {/*...*/}
        }

在上面的示例中,T在 Add方法的上下文中是一个类型约束,而在 List 类的上下文中是一个未绑定的类型参数。

类型参数还可在泛型类定义中用作约束。 请注意,必须在尖括号中声明此类型参数与任何其他类型的参数:

SampleClass<T, U, V> where T : V { }
8> 为泛型方法添加约束
        void SwapIfGreater<T>(ref T lhs, ref T rhs) where T : System.IComparable<T>
        {
            T temp;
            if (lhs.CompareTo(rhs) > 0)
            {
                temp = lhs;
                lhs = rhs;
                rhs = temp;
            }
        }

泛型方法可以使用许多类型参数进行重载。 例如,下列方法可以全部位于同一个类中:

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

4. 泛型接口:

语法:

     interface ITest1<K> 
    {

    }

一个接口可定义多个类型参数,如下所示:

     interface ITest1<K, V> 
    {

    }

适用于类的继承规则同样适用于接口:

     interface ITest1<S> 
    {

    }

    interface ITest2<K> : ITest1<K>
    {
         
    }

泛型接口的约束:

    interface ITest1<S> where S : class
    {

    }

泛型接口的约束继承

     interface ITest1<S> where S : class
    {
        
    }

    interface ITest2<K> : ITest1<K> where K : class
    {
         
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容