• 第三章 C# 泛型


    当两个模块功能相似,仅仅只是类型不同的时候,你会怎么办呢。请看以下代码:

    public class IntClass
            {
                List<int> Intlist = new List<int>();
                public void AddList(int i)
                {
                    Intlist.Add(i);
                }
            }
            public void Main()
            {
                IntClass c1 = new IntClass();
                c1.AddList(1);
                c1.AddList(1);
            }
    View Code

    但是当我们想c1.AddList("hello word");要插入一个字符串类型的时候,你会怎么做呢?

    二逼程序员会这样做:

    public class StringClass
            {
                List<string> Intlist = new List<string>();
                public void AddList(string i)
                {
                    Intlist.Add(i);
                }
            }
    View Code

    普通程序员会这样做:

    public class ObjClass
            {
                List<object> Intlist = new List<object>();
                public void AddList(object i)
                {
                    Intlist.Add(i);
                }
            }
    View Code

    仔细想想,不断装箱拆箱是否效率低下呢,当我们要插入bool,char,datetime.....等等类型的时候,我们需要copy这么多类吗?这时我们就用到了泛型。

    1.泛型的声明:

    public class Class1<T>
        {
            private List<T> List = new List<T>();
            public List<T> GetList()
            {
                return List;
            }
            public void AddList(T t)
            {
                List.Add(t);
            }
        }
    View Code

    2.泛型的默认值:

    T t=defalut(T); 如果T是值类型,则t=0;如果T是引用类型,则t=null.

    3.泛型约束:

     接口约束:where T:Interface   必须显示的实现接口

     基类约束:where T:BaseClass 参数必须为BaseClass或者派生类

     类约束:where T:class T必须是引用类型

     值类型约束: where T:struct T必须是值类型

     构造函数约束: where T:new()  必须有默认的构造函数

     泛型类型约束: Where T:T1

    4静态成员:

    不同类型的泛型可以认为是不同的类。  所有静态成员只能在同类中共享。

    public class mm<T>
    {
    public static string Name{get;set;}
    }

    mm<int> a,mm<int> b,mm<sting>c       a,b可以共享Name,c不能

    5.泛型类中的方法重载
    方法的重载在.Net Framework中被大量应用,他要求重载具有不同的签名。在泛型类中,由于通用类型T在类编写时并不确定,所以在重载时有些注意事项,这些事项我们通过以下的例子说明:

    public class Node<T, V>

        {

            public T add(T a, V b)          //第一个add

            {

                return a;

            }

            public T add(V a, T b)          //第二个add

            {

                return b;

            }

            public int add(int a, int b)    //第三个add

            {

                return a + b;

            }

    }

    上面的类很明显,如果T和V都传入int的话,三个add方法将具有同样的签名,但这个类仍然能通过编译,是否会引起调用混淆将在这个类实例化和调用add方法时判断。请看下面调用代码:

    Node<int, int> node = new Node<int, int>();

        object x = node.add(2, 11);

    这个Node的实例化引起了三个add具有同样的签名,但却能调用成功,因为他优先匹配了第三个add。但如果删除了第三个add,上面的调用代码则无法编译通过,提示方法产生的混淆,因为运行时无法在第一个add和第二个add之间选择。

    Node<string, int> node = new Node<string, int>();

            object x = node.add(2, "11");

       这两行调用代码可正确编译,因为传入的string和int,使三个add具有不同的签名,当然能找到唯一匹配的add方法。

    由以上示例可知,C#的泛型是在实例的方法被调用时检查重载是否产生混淆,而不是在泛型类本身编译时检查。同时还得出一个重要原则:

    当一般方法与泛型方法具有相同的签名时,会覆盖泛型方法。

    泛型类的方法重写
    方法重写(override)的主要问题是方法签名的识别规则,在这一点上他与方法重载一样,请参考泛型类的方法重载。

    泛型的使用范围
    本文主要是在类中讲述泛型,实际上,泛型还可以用在类方法、接口、结构(struct)、委托等上面使用,使用方法大致相同,就不再讲述。

     

  • 相关阅读:
    第八章 Python 对象和类
    第七章 Python 盒子:模块、包和程序
    第六章 Python 函数(二)
    第五章 Python 函数(一)
    VS的32位、64位预处理定义;
    python 3D散点绘图;
    基于生长的棋盘格角点检测算法解读
    C++11: std::function<void()> func;
    有关pyinstaller打包程序后,转到其他电脑报“Failed to excute script"的问题;
    Qt: 监听文件夹QFileSystemWatcher;
  • 原文地址:https://www.cnblogs.com/housh/p/4709523.html
Copyright © 2020-2023  润新知