• C#学习笔记之——泛型(Generic)


    泛型是将类型作为参数来传递。

    泛型的优点:

    1、使用泛型可以重用代码,保护类型的安全以及提高性能

    为什么这样说,这里就有个例子

    public void Swap(int x, int y)
    {
    	int temp = x;
    	x = y;
    	y = temp;
    }
    public void Swap(char x, char y)
    {
    	char temp = x;
    	x = y;
    	y = temp;
    }
    public void Swap(string x, string y)
    {
    	string temp = x;
    	x = y;
    	y = temp;
    }


    可以看到相同的写法,只是参数不一样,这样写就特别浪费空间

    2、降低强制转换或装箱操作的成本和风险

    像上面这个代码确实可以用另一种方式代替,就是用object

    public void Swap(object x, object y)
    {
    	object temp = x;
    	x = y;
    	y = temp;
    }


    比如这样,但是用object会出现装拆箱操作,这将在托管堆上分配和回收大量的变量,若数据量大,则性能损失非常严重。在处理引用类型时,虽然没有装箱和折箱操作,但将用到数据类型的 强制转换操作,增加处理器的负担。

    3、可以对泛型参数进行限定以访问特定数据类型的方法

    可以限定数据类型

    泛型类型参数的约束:关键字where

    泛型类型参数常用的约束类型

    1、where T:struct  要求是值类型参数

    2、where T:class 要求是引用类型参数

    3、where T:new() 要求这个泛型具有一个无参构造方法,如果有多个约束,这个要放在最后

    4、where T:基类名 这个泛型是该父类或其子类

    5、where T:接口名 泛型是实现了该接口的类型

    6、where T:int(,string,char,bool等)

    泛型类型参数注意点

    1、泛型类型参数可以有多个

    public void Swap<T, U> (T t, U u) { ... }

    2、泛型类型参数可以是编译器识别的任何数据类型

    3、泛型类型参数命名需要遵守命名规则

    (1)使用描述性名称命名泛型类型,并且使用T作为前缀

    (2)使用单个大写字母命名即可

    泛型方法

    格式: 访问修饰符 返回值类型 方法名<泛型类型参数>(参数列表){
    方法体
    }

    调用的时候要加上具体参数类型,比如:

    Swap<int, int>(a, a);

    泛型方法重载

    可以泛型类型参数进行重载

    public void Swap() { }
    public void Swap<T> {}
    public void Swap<T, U> {}

    泛型结构

    修饰符 struct 结构体名<泛型类型参数>{
        结构体成员
    }

    struct PieceOfData<T>
    {
        public PieceOfData(T value)
        {
            _data = value;
        }
        private T _data;
        public T Data
        {
            get{ return _data; }
            set{ _data = value; }
        }
    }


    泛型类

    修饰符 class 类名<泛型类型参数>{
    类成员
    }

    public class Student<T>
    {
         类成员
    }

    泛型接口

    修饰符 interface 接口名<泛型类型参数>{

    }

    public interface IMyInterface<T>
    {
        T ReturnIt(T inValue);
    }

    协变(convariance)、逆变(contravariance)和不变(invariance)

    协变

    class MyClass
    {
        static Dog MakeDog()
        {
            return new Dog();
        }
        static void Main(string[] args)
        {
            //Animal a1 = new Animal();
            //Animal a2 = new Animal();
    
            Facttory<Dog> dogMaker = MakeDog;
            Facttory<Animal> animalMaker = dogMaker;//委托中泛型类型参数前不加out要报错
    
            Console.WriteLine(animalMaker().NumberOfLegs.ToString());
        }
    }
    
    //动物类
    class Animal
    {
        public int NumberOfLegs = 4;   
    }
    
    //狗类,继承自动物类
    class Dog : Animal
    {
    }
    
    delegate T Facttory<out T>();
    

    逆变

    class MyClass
    {
        delegate void Action1<in T>(T a);//in:逆变关键字
    
        static void ActOnAnimal(Animal a)
        {
            Console.WriteLine(a.NumberOfLegs);
        }
    
        static void Main(string[] args)
        {
            Action1<Animal> act1 = ActOnAnimal;
            Action1<Dog> dog1 = act1;
            dog1(new Dog());
        }
    }
    
    //动物类
    class Animal
    {
        public int NumberOfLegs = 4;   
    }
    
    //狗类,继承自动物类
    class Dog : Animal
    {
    }
    

    不变

    不包括in和out关键字的委托和接口类型参数叫做不变。这些类型参数不能用于协变或逆变。 

  • 相关阅读:
    WebLogic10 & MyEclipse 配置(转)
    java中的接口隔离(ISP)
    java多线程之 wait(),notify(),notifyAll()
    Windows Server 2008 R2终端服务器激活方法
    [zt]PHP+jQuery+Ajax实现用户登录与退出
    USACO Window AreaDFS矩形切割
    eWebEditor在IE8,IE7下所有按钮无效之解决办法
    [zt]【HoorayOS】开源的Web桌面应用框架——安装部署
    javascript Date format(js日期格式化)
    web design
  • 原文地址:https://www.cnblogs.com/AlinaL/p/12852179.html
Copyright © 2020-2023  润新知