• C# 泛型


    委托让方法参数化,而泛型实现了类型参数化。

    一、泛型类型的声明规则:

      1、在类名称后跟一对尖括号,括号中为若干个类型参数,多个类型参数之间使用逗号进行分隔,类型参数实际上是个类型占位符。如、public class MyClass<T>{},T只是个习惯,实际上用其他字母也完全可以。

      2、在类声明的主体中使用类型参数来表示应该被替代的类型,一般是方法的参数类型,返回类型,或者作为字段、属性的类型。

      示例1:

    复制代码
        public class MyClass<T1, T2>
        {
            public T1 field1;   //在类内部泛型类型还能用
            public T2 field2;
    
            public T1 GetField1()  //作为返回值
            { 
                return field1;
            }
    
            public T2 GetField2()
            {
                return field2;
            }
    
            public void SetField1(T1 data)  //作为方法参数类型
            {
                field1 = data;
            }
    
            public void SetField2(T2 data)
            {
                field2 = data;
            }
        }
    复制代码

      泛型能够根据传入的不同类型,实施不同的处理。重用了代码逻辑,将类型抽象了出来。

      泛型的类型约束,通过约束能够对类型实参添加一定的限制条件,约束是通过使用上下文关键字的where应用的,只需要在泛型类型声明的尖括号后面使用where关键字,后面紧跟类型参数和约束类型,中间使用冒号分隔即可。

      类型约束一共有6种,如下所示:

    约束类型 说明
    where T : class 类型实参必须是引用类型,包括任何类、接口、委托或数组类型
    where T : struct 类型实参必须是值类型,可以是任何值类型,但不包括Nullable
    where T : <基类名> 类型必须是指定的类或者它的派生类
    where T : <接口名> 类型必须是实现了指定的接口或者实现了该接口的类型,可以指定多个接口约束,约束接口也可以是泛型的
    where T : new() 类型实参必须有一个无参数的公共构造函数
    where T : U 类型实参T必须是类型实参U,或者是U的派生类,这称作裸类型约束

      同时还必须要注意,当需要添加多个类型约束时,约束之间用逗号分隔。同时对于某一个类型参数的多种约束类型,where字句与where字句之间没有次序要求,但是对于where字句内部是有次序要求的。具体次序如下:

    1.   如果有class,struct,基类这三种类型约束,则必须放在第一位。
    2.   之后是接口约束,数量不限
    3.   如果有new(),则必须放在最后。

      如:

        public class TestType<T,V> where T : Person where V : new(){} //where与where字句没有次序要求
        public class TestType<T> where T : class,IList,new(){}      //where字句内部有类型要求
    复制代码
        class Program
        {
            static void Main(string[] args)
            {
                Person P = new Person();
                P.Id = 1;
                P.Name = "张三";
    
                TestType<Person> tt = new TestType<Person>();
                string str = tt.getType(P);
                Console.WriteLine(str);     //输出张三
                Console.ReadKey();
            }
        }
    
        public class TestType<T> where T : Person  //指定实参类型必须是Person类或Person类的派生类
        {
            public string getType(T data)
            {
                return data.Name;
            }
        }
    
    
        public class Person
        {
            public int Id;
            public string Name;
        }
    复制代码

     泛型方法与泛型类很相似。一下给出两个泛型方法的例子。

    复制代码
        class Program
        {
            static void Main(string[] args)
            {
                Person p = new Person();
                p.Id = 1;
                SetName<Person>(p);
                Console.WriteLine(p.Name);  //输出张飞
    
                Console.ReadKey();
            }
    
            public static Person SetName<T>(T per) where T : Person
            {
                per.Name = "张飞";
                return per;
            }
        }
    
        class Person
        {
            public int Id { get; set; }
    
            public string Name { get; set;  }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                string str = "你好!";
                Console.WriteLine(GetMessage<string>(str));     //输出System.String
    
                Console.ReadKey();
            }
    
            public static Type GetMessage<T>(T Message)
            {
                return Message.GetType();
            }
        }    
    复制代码

     泛型的扩展方法,与扩展方法一样,只是有点怪异罢了。给个示例:

    复制代码
        class Program
        {
            static void Main(string[] args)
            {
                Person<string> per = new Person<string>();
                per.Person<string>("关羽");   //这样子来调用扩展方法,自己都看不懂牛得一B
                Console.WriteLine(per.Name);
                Console.ReadKey();
            }
        }
    
        public static class Set
        {
            public static void Person<T>(this Person<T> p, T Name)
            {
                p.Name = Name;
            }
            
        }
    
    
        public class Person<T>
        {
            public int Id { get; set; }
    
            public T Name { get; set; }
        }
    复制代码

    泛型委托和非泛型委托也很相似,只是泛型委托进行了一层抽象,将中间涉及的操作类型以及返回值类型抽象为了类型参数,以便更大限度地复用该委托。 

    复制代码
        public delegate T PrintDelegate<T>(T data);
        class Program
        {
            static void Main(string[] args)
            {
                PrintDelegate<string> StrDelegate = PString; //委托的定义中,3个大T都是string
                string outStr = StrDelegate("我是一个兵");   //调用委托
                Console.WriteLine(outStr);         //输出委托返回值    我是一个兵我是一个兵
    
                PrintDelegate<int> IntDelegate = PInt;  //类型参数传入int,则参数类型,返回值类型,都是int
                int outInt = PInt(3);   //由于参数类型设为了int,因此只能绑定参数跟返回值为int的方法
                Console.WriteLine(outInt);  //输出    6
    
    
                Console.ReadKey();
            }
    
            public static string PString(string str)
            {
                return str + str;
            }
    
            public static int PInt(int i)
            {
                return i + i;
            }
        }
    复制代码

    泛型的协变与逆变

  • 相关阅读:
    点击鼠标上下滚动
    点击小圆圈切换图片(基础)
    js取整数、取余数的方法
    几张图片滚动切换
    (转)iPhone +ipad尺寸规范(界面 & 图标)
    基础选择分类
    JDBC事务
    JDBC
    mysql
    网络编程三要素
  • 原文地址:https://www.cnblogs.com/mingxuantongxue/p/3805977.html
Copyright © 2020-2023  润新知