zoukankan      html  css  js  c++  java
  • 泛型

    泛型

    泛型允许你在编译时实现类型安全。它们允许你创建一个数据结构而不限于一特定的数据类型。然而,当使用该数据结构时,编译器保证它使用的类型与类型安全是相一致的。泛型提供了类型安全,但是没有造成任何性能损失和代码臃肿

    泛型优势

    • 类型安全

    • 避免装箱拆箱带来的性能损耗

    • 二进制代码重用

    非泛型集合

    var arr1 = new ArrayList();
    arr1.Add(10);//Add方法参数值是object类型,这里将int->object
    arr1.Add("wang");//Add方法参数值是object类型,这里将int->object
    foreach (int item in arr1)//这里如果用int类型遍历集合,就挂掉了
    {
        Console.WriteLine(item);//读取时要进行拆箱
    }

     泛型集合

    /*泛型集合在使用时定义好类型,之后就不存在装箱拆箱;
     * 因为已经定义当前集合只能存入int类型,也就不能存入其他类型
     * 编译时就会报错,错误应及早发现
     */
    var arr2 = new List<int>();
    arr2.Add(10);
    foreach (var item in arr2)
    {
        Console.WriteLine(item);
    } 

    通过参数化类型来实现在同一份代码上操作多种数据类型,利用“参数化类型”将类型抽象化,从而实现灵活的复用。每个集合的详细规范可以在System.Collection.Generic名称空间下找到

    泛型的适用场景

    打印int,string类型参数

        class Print
        {
            public static void PrintInt(int parameter)
            {
                Console.WriteLine("This is {0},parameter={1},type={2}",
                   typeof(Print).Name, parameter.GetType().Name, parameter);
            }
    
            public static void PrintString(string parameter)
            {
                Console.WriteLine("This is {0},parameter={1},type={2}",
                   typeof(Print).Name, parameter.GetType().Name, parameter);
            }
        }

    如果需要继续添加打印double或者其他类型参数就需要继续添加方法;使用继承object类处理,因为object是所有类型的基类

        class Print
        {
            public static void PrintObject(object parameter)
            {
                Console.WriteLine("This is {0},parameter={1},type={2}",
                   typeof(Print).Name, parameter.GetType().Name, parameter);
            }
        }

     这么做看起来解决了这个问题,考虑下面的情形(没有实际意义,仅做学习参考)

    class Print
        {
            public static void PrintObject(object parameter)
            {
                int str = 0;
                str += (int)parameter;
                Console.WriteLine("This is {0},parameter={1},type={2}",
                   typeof(Print).Name, parameter.GetType().Name, str);
            }
        }
    class Program
        {
            static void Main(string[] args)
            {
                Print.PrintObject(1);
                Print.PrintObject(true);
                Console.ReadKey();
            }
        }

    再比如这样

                ArrayList list = new ArrayList();
                list.Add(50);
                list.Add("哈哈");
    //如果使用整数对象来使用foreach语句进行遍历的话,当编译器接受到代码,但是因为集合中的所有元素都不是整数,所以会导致运行时异常
    foreach (int i in list) { Console.WriteLine(i); }

    当传值为int类型1时,代码是可以正常运行的,但传值为true就会造成类型转换错误,并且编译时并没有获取到这个错误,这说明当前的方法并不是类型安全的;而且使用object类会造成大量的装箱/拆箱操作,这对性能也有很大损耗

    这种时候就可以考虑使用泛型来实现

    泛型方法

        class Print
        {
            /// <summary>
            /// Object方法处理打印各种类型值
            /// </summary>
            /// <param name="parameter"></param>
            public static void PrintObject(object parameter)
            {
                Console.WriteLine("This is {0},parameter={1},type={2}",
                   typeof(Print).Name, parameter.GetType().Name, parameter);
            }
            
            /// <summary>
            /// 泛型方法处理打印各种类型值
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="tParameter"></param>
            public static void PrintT<T>(T tParameter)
            {
                Console.WriteLine("This is {0},parameter={1},type={2}",
                  typeof(Print).Name, tParameter.GetType().Name, tParameter);
            }
        }

     泛型类

        class Program
        {
            static void Main(string[] args)
            {
                Print<int> iPrint = new Print<int>();
                iPrint.t = 123;
                Print<string> sPrint = new Print<string>();
                sPrint.t = "123";
                Console.ReadKey();
            }
        }
        class Print<T>
        {
            public T t;
        }

    default

    泛型default用于将泛型类型初始化为null或0

    T t=default(T);

     泛型接口

        interface IPrint<T>
        {
            T GetT(T t);
        }

    泛型委托

    public delegate void Print<T>(T t);

    泛型在声明的时候可以不指定具体的类型,但是在使用的时候必须指定具体类型

     Print<int> iPrint = new Print<int>();//这里的类型是int

    如果存在继承并且子类也是泛型的,那么继承的时候可以不指定具体类型

        class Print<T>
        {
            public T t;
        }
        
    //这里继承时没有指定泛型类型
    class ConsolePrint<T> : Print<T> { }

    同上,类实现泛型接口也是如此

    泛型约束

     T:calss 类型参数必须是引用类型,包括任何类、接口、委托或数组类型
     T:stauct 类型参数必须是值类型。可以指定除 Nullable 以外的任何值类型
     T:new() 类型参数必须具有无参数的公共构造函数。当与其他约束一起使用时,new() 约束必须最后指定
     T:<基类名> 类型参数必须是指定的基类或派生自指定的基类
     T:<接口名称> 类型参数必须是指定的接口或实现指定的接口。可以指定多个接口约束。约束接口也可以是泛型的
    T1:T2 类型T1派生自泛型类型T2,该约束也被称为裸类型约束
        class Person
        {
            public static void PintSayHello()
            {
    
            }
        }
    
        interface ISport
        {
            void Sport();
        }
    
        /// <summary>
        /// 约束T必须是Person类型或者是Person的子类并且实现了ISport接口且T类型中必须有无参构造函数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        class Show<T> where T : Person, ISport, new()
        {
    
        }
    
        /// <summary>
        /// 约束T必须是引用类型并且实现了ISport接口且T类型中必须有无参构造函数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        class Show2<T> where T : class, ISport, new()
        {
    
        }
    
        /// <summary>
        /// 约束T必须是值类型并且实现了ISport接口
        /// </summary>
        /// <typeparam name="T"></typeparam>
        class Show3<T> where T : struct, ISport
        {
    
        }

    注意:泛型约束可以同时约束多个,有多个泛型约束时,new()约束一定是在最后

    参考:

    https://www.cnblogs.com/dotnet261010/p/9034594.html

    https://www.cnblogs.com/yilezhu/p/10029782.html

    https://www.cnblogs.com/aehyok/p/3384637.html

  • 相关阅读:
    binary tree解题模板
    done infosys 八股文springboot员工管理系统
    好题 telus国际_从镜子里看到另一台显示器的面试
    done 对于spring boot oa的面试思考
    done 有一点题 infosys 秀出你的ID spring经历问得很细
    Eliassen Group vendor 检测眼球视线的oa 又细又多做不完
    done tek 把你从牛角尖钻出来的node list算法题
    contagious.ly 自豪的纽约客,政府vendor
    Apple screening carlos白人 头晕脑胀的三道简单算法题
    done apple_Infosys_Jugal 要求完整写出Java8 stream
  • 原文地址:https://www.cnblogs.com/GnailGnepGnaw/p/10606944.html
Copyright © 2011-2022 走看看