• C# 泛型学习总结


    参考:http://www.cnblogs.com/jimmyzhang/archive/2007/08/04/842663.html

      对泛型的理解进行梳理,学习博客园大师的文章,并将之变成自己的东西,再加之自己的理解想陈述的更加简单直观些,能力有限,且文笔功底略显不足,因此如有欠妥之处请不吝赐教。——写在前面

    泛型如何理解?

    1.实现代码复用,无须对不同类型编写近乎相同的代码(仅仅参数类型不同)。而实际上Console.Write()方法也并未采用泛型,因此出现下图若干重载函数,至于为什么未采用泛型在此不做研究。

    2.使用了泛型的集合可以保证其类型安全以及可以避免集合添加元素、取出元素时候的装箱、拆箱操作。

    一个简单的例子

       初学泛型曾看了一些文章,好像大都直接拿泛型集合说事,本人比较不够聪明,总以为泛型仅仅用于泛型集合的,以至于很长时间以来一想到泛型就想到泛型集合。如果有园友初学泛型,那么暂且不要关心泛型集合,只关心泛型,且看如下例子。

        我们需要将两个值ToString()后再相加并输出到屏幕,那么我们可能会像如下这么写(可能这么简单的功能没人会像如下这么做,大概会只封装一个以string为参数的函数,在传参的时候ToString(),此处只是为了举例的方便,假设函数没那么简单的情况下):

        class MyHelper
        {
            public static void AddAndPrint(int i, int j)
            {
                Console.WriteLine(string.Format("The value is {0}", i.ToString() + "@" + j.ToString()));
            }
            public static void AddAndPrint(float i, float j)
            {
                Console.WriteLine(string.Format("The value is {0}", i.ToString() + "@" + j.ToString()));
            }
            public static void AddAndPrint(double i, double j)
            {
                Console.WriteLine(string.Format("The value is {0}", i.ToString() + "@" + j.ToString()));
            }
        }
    

     请注意,上面三个AddAndPrint函数除了参数类型以外,函数体内部实现完全一样。那么我们会这样调用它们:

            static void Main(string[] args)
            {
                MyHelper.AddAndPrint(100, 120);
                MyHelper.AddAndPrint(100.123F, 120F);
                MyHelper.AddAndPrint(100.456D, 120.666D);
                Console.ReadKey();
            }
    

     那么很容易就可以想到,AddAndPrint函数仅仅参数类型不一样却“不得不”写了三次(如果是更多次呢),这显然是不能接受的。这时候我们可以通过泛型来进行代码重用。三个函数参数类型分别是int、float、double,那么我们合并三个函数为一个函数,参数类型就不能是任一确定类型,我们可以假定这个类型是T(取自Type首字母,当然.net许多类库的代码会使用诸如TEntityTElement之类的替代符可能更容易理解),那么我们可以将如上三个函数进行合并,如下:

            public static void AddAndPrint(T t1, T t2)
            {
                Console.WriteLine(string.Format("The value is {0}", t1.ToString() + "@" + t2.ToString()));
            }
    

     那么可以通过如下方式将类型传入(因为是静态函数,因此每次调用的时候在类名后面以如<int>的形式指定其类型,如果调用非静态函数,那么在调用构造函数的时候指定即可):

        class MyHelper<T>
        {
             ...
         }
    

     注意,MyHelper<T>与AddAndPrint(T t1, T t2)须一致,当然也可以有多种类型,如MyHelper<T1,T2>与AddAndPrint(T1 t1,T2 t2),完整代码如下:

        class MyHelper<T>
        {
            public static void AddAndPrint(T t1, T t2)
            {
                Console.WriteLine(string.Format("The value is {0}", t1.ToString() + "@" + t2.ToString()));
            }
        }
    
            static void Main(string[] args)
            {
                MyHelper.AddAndPrint(100, 120);
                MyHelper.AddAndPrint(100.123F, 120F);
                MyHelperAddAndPrint(100.456D, 120.666D);
                Console.ReadKey();
            }
    

     泛型集合简单例子

         其实泛型集合不过是在编写集合类(以及其节点Node类)时采用泛型而已。下面就以一个简单的单向链表为例。

    MyNode类,不指定Data的类型,以占位符T代替:

    class MyNode<T>
        {
            public MyNode(T t)
            {
                this.Data = t;
            }
            public T Data { get; set; }
            public MyNode<T> Next { get; set; }
            public override string ToString()
            {
                return Data.ToString();
            }
        }

     那么我们的MyList类可以像下面这样,仅仅简单实现添加功能:

    class MyList<T>
        {
            public MyNode<T> Head { get; set; }
            public MyList(T t)
            {
                Head = new MyNode<T>(t);
            }
            public void Append(T t)
            {
                MyNode<T> temp = this.Head;
                while (temp.Next != null)
                {
                    temp = temp.Next;
                }
                MyNode<T> newNode = new MyNode<T>(t);
                temp.Next = newNode;
            }
            public override string ToString()
            {
                StringBuilder sb = new StringBuilder();
                MyNode<T> temp = this.Head;
                int index = 0;
                do
                {
                    sb.Append(string.Format("The {0} Element is {1}\n", index, temp.Data.ToString()));
                    index++;
                    temp = temp.Next;
                }
                while (temp != null);
                return sb.ToString();
            }
        }
    

     调用:

            static void Main(string[] args)
            {
                  MyList<string> myList = new MyList<string>("first");
                  myList.Append("second");
                  MyList<int> mylist2 = new MyList<int>(12);
                  mylist2.Append(1231);
                  Console.WriteLine(mylist2.ToString());
                  Console.ReadKey();
            }
    
  • 相关阅读:
    【内存泄漏】方法三:利用linux的valgrind命令定位内存泄露(Memory Leak)
    【内存泄漏】方法二:利用linux的mtrace命令定位内存泄露(Memory Leak)
    Windows下sqlmap的使用_01
    关于安装和使用BurpSuite及Java环境的配置问题
    Windows下修改环境变量的几种方法
    OPPO VOOC快充原理
    在线代码运行
    Linux在线学习模拟器
    socket设置为非阻塞模式
    pthread_mutexattr_t设置的相关函数及其说明
  • 原文地址:https://www.cnblogs.com/ziyeyimeng/p/2821811.html
Copyright © 2020-2023  润新知