zoukankan      html  css  js  c++  java
  • 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关键字的委托和接口类型参数叫做不变。这些类型参数不能用于协变或逆变。 

  • 相关阅读:
    《.NET内存管理宝典 》(Pro .NET Memory Management) 阅读指南
    《.NET内存管理宝典 》(Pro .NET Memory Management) 阅读指南
    《.NET内存管理宝典 》(Pro .NET Memory Management) 阅读指南
    使用Jasmine和karma对传统js进行单元测试
    《.NET内存管理宝典 》(Pro .NET Memory Management) 阅读指南
    《.NET内存管理宝典 》(Pro .NET Memory Management) 阅读指南
    nginx 基于IP的多虚拟主机配置
    Shiro 框架的MD5加密算法实现原理
    项目实战:Qt+OSG三维点云引擎(支持原点,缩放,单独轴或者组合多轴拽拖旋转,支持导入点云文件)
    实用技巧:阿里云服务器建立公网物联网服务器(解决阿里云服务器端口,公网连接不上的问题)
  • 原文地址:https://www.cnblogs.com/AlinaL/p/12852179.html
Copyright © 2011-2022 走看看