zoukankan      html  css  js  c++  java
  • .NET泛型01,为什么需要泛型,泛型基本语法

    .NET泛型或许是借鉴于C++泛型模版,借助它可以实现对类型的抽象化、泛型处理,实现了类型和方法之间的解耦。一个最经典的运用是在三层架构中,针对不同的领域模型,在基接口、基类中实现针对各个领域模型的泛型处理。

    本篇主要包括:
    为什么需要泛型
        ※ 不用泛型
        ※ 使用泛型
        ※ 泛型的运行时本质
    泛型语法
    典型的泛型类

      为什么需要泛型

      不用泛型

    来看一个比较类型的方法。

    public class Calculator
        {
            public static bool AreEqual(int value1, int value2)
            {
                return value1 == value2;
            }
        }


    在客户端调用。

    class Program
        {
            static void Main(string[] args)
            {
                bool result = Calculator.AreEqual(1, 2);
                if (result)
                {
                    Console.WriteLine("相等");
                }
                else
                {
                    Console.WriteLine("不等");
                }
                Console.ReadKey();
            }
        }


    运行结果:不等

      不用泛型的缺点一:不是类型安全

    如果我们想使用现在的方法来比较字符串类型。

    bool result = Calculator.AreEqual("A", "B");

    这时,看到编译器报错。从这点来看,AreEqual()方法不是类型安全的方法,当输入string类型,编译器就会报错。

    如果把AreEqual()方法的参数类型改成object,编译器就不再报错。

    public class Calculator
        {
            public static bool AreEqual(object value1, object value2)
            {
                return value1 == value2;
            }
        }

    以上,运行也正常。

      不用泛型的缺点二:装箱与拆箱导致性能降低

    现在,对于AreEqual(object value1, object value2),从方法本身来讲是没有问题的,但在客户端调用的时候,比如我们还是想比较值类型。

    bool result = Calculator.AreEqual(1, 2);

    在运行时,当整型值类型参数1和2传递、赋值给AreEqual(object value1, object value2)中的引用类型参数value1和value2的时候,发生了一次"装箱"操作。而当把引用类型转换成值类型的时候,又会发生一次"拆箱"操作,这导致性能的降低。

      使用泛型

    把AreEqual()改成泛型方法。

    public class Calculator
        {
            public static bool AreEqual<T>(T value1, T value2)
            {
                return value1.Equals(value2);
            }
        }

    于是,在客户端可以这样:

    bool result = Calculator.AreEqual<string>("A", "A"); 
    bool result = Calculator.AreEqual<int>(5, 3);

    由此,使用泛型的好处有:
    1、实现了方法和类型的解耦。
    2、不会造成类型转换,规避了因装箱于拆箱引起的性能问题。
    3、泛型保证了类型的绝对安全。

    当然,还可以把T的位置放在类上:

    public class Calculator<T>
        {
            public static bool AreEqual(T value1, T value2)
            {
                return value1.Equals(value2);
            }
        }

    然后这样使用:

    bool result = Calculator<string>.AreEqual("A", "A"); 
    bool result = Calculator<int.AreEqual(1, 2);


     

      泛型的运行时本质

    CLR中有专门的IL指令支持泛型操作。
    →初次编译时,生成IL代码和元数据,T只是类型占位符,在编译时不进行实例化
    →JIT编译时,以实际类型替换元数据中的T占位符
    →将元数据转换为本地代码

      泛型语法

    class MyArray<T> where T : Student, new()
    {
        private T[] _items;
        public T myData;
    
        public MyArray()
        {
            myData = default(T);
        }
    
        public void Add(T item)
        {}
    }

    创建泛型实例要指定实际的数据类型:
    MyArray<Int32> myArr = new MyArray<Int32>();

    值类型的默认值为0,引用类型的默认值为null,使用泛型默认值:
    myData = default(T);

    泛型约束:
    T : 基类名,表示必须是基类名的派生类
    T :new(), 表示必须具有无参构造函数,new()约束必须放在最后面
    T :struct, 表示必须是值类型
    T :class, 表示必须是引用类型
    T :接口名,表示必须实现该接口,或实现该接口的接口

    泛型类本质上仍然是一个类,依然可以继承:

    internal class GenericeComparer<T> : Comparer<T> where T : IComparable<T>
    class MyArray<T> : ArrayList

      典型的泛型类

    在System.Collections.Generic命名空间和System.Collections.ObjectModel中,定义了不同的泛型类和泛型接口,这些泛型多为集合类。

    List<T> 对应ArrayList集合类
    SortedList<TKey, TValue> 对应SortedList集合类
    Queue<T> 先进先出的集合类
    Stack<T> 后进先出的集合类
    Collection<T> 自定义泛型集合的基类
    Dictionary<TKey, TValue> 对应于Hashtable集合类

    参考资料:
    《你必须知道的.NET(第2版)》,作者王涛。

    ".NET泛型"系列包括:

    .NET泛型01,为什么需要泛型,泛型基本语法

    .NET泛型02,泛型的使用

    .NET泛型03,泛型类型的转换,协变和逆变

    .NET泛型04,使用Lazy<T>实现延迟加载

  • 相关阅读:
    easy Html5 Jquery Mobile之ToolBars(Header and Footer)
    Windows Phone7 性能
    easy Html5 Jquery Mobile之Buttons
    开篇,从这里开始。
    SkyDrive APIs——用户登录和APP授权(2)
    Windows Phone的强大语音控制,让你的Phone大秀一把
    SkyDrive APIs之——操作文件和文件夹(3)
    Mango in my mind 之 Live Tile
    SkyDrive APIs——搭建环境(1)
    windows10安装redis
  • 原文地址:https://www.cnblogs.com/darrenji/p/3850445.html
Copyright © 2011-2022 走看看