zoukankan      html  css  js  c++  java
  • 四、泛型(第三部分)

    2.创建泛型类

      首先介绍一个一般的、非泛型的简化链表类,它可以包含任意类型的对象,以后再把这个类转化为泛型类,以后再把这个类转化为泛型类型。

      在链表中,一个元素引用下一个元素。所以必须创建一个类,它将对象封装在链表中,并引用下一个对象。类LinkedListNode包含一个属性value,该属性用构造函数初始化。另外,LinkedListNode类包含对链表中下一个元素和上一个元素的引用,这些元素都可以从属性中访问(代码文件LinkedListObjects/LinkedListNode.cs)。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleApplication8
    {
        class LinkedListNode
        {
            private object m_value;
            public object Value
            {
                get
                {
                    return m_value;
                }
                set
                {
                    m_value = value;
                }
            }
    
            public LinkedListNode(object _value)
            {
                this.m_value = _value;
            }
    
            public LinkedListNode Next
            {
                get
                {
                    return this;
                }
                internal set
                {
                    //this = value;
                    Next = value;
                }
            }
    
            public LinkedListNode Prev
            {
                get
                {
                    return this;
                }
                internal set
                {
                    //this = value;
                    Prev = value;
                }
            }
        }
    
    
    }

      LinkedList类包含LinkedListNode类型的First和Last属性,它们分别标记了链表的头尾。AddLast()方法在链表尾添加了一个新元素。首先创建一个LinkedListNode类型的对象。如果链表是空的,First和Last属性就设置为该新元素;否则,就把新元素添加为链表的最后一个元素。通过实现GetEnumerator()方法,可以用foreach语句遍历链表。GetEnumerator()方法使用yield语句创建一个枚举器类型。

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleApplication8
    {
        class LinkedList : IEnumerable
        {
            public LinkedListNode First
            {
                get
                {
                    return First;
                }
                set
                {
                    First = value;
                }
            }
    
            public LinkedListNode Last
            {
                get
                {
                    return Last;
                }
                set
                {
                    Last = value;
                }
            }
    
            public LinkedListNode AddLast(object _node)
            {
                var newNode = new LinkedListNode(_node);
                if (First == null)
                {
                    First = newNode;
                    Last = First;
                }
                else
                {
                    LinkedListNode pervious = Last;
                    Last.Next = newNode;
                    Last = newNode;
                    Last.Prev = pervious;
                }
    
                return newNode;
            }
    
            public IEnumerator GetEnumerator()
            {
                LinkedListNode current = First;
                while (current != null)
                {
                    yield return current.Value;
                    current = current.Next;
                }
            }
        }
    }

      现在可以对于任意类型使用LinkedList类了。在下面的代码中,实例化了一个新的LinkedList对象,添加了两个整数类型和一个字符串类型。整数类型要转换为一个对象,所以执行装箱操作,如前面所述。通过foreach语句执行拆箱操作。在foreach语句中,链表中的元素被强制转换为整数,所以对于链表中的第三个元素,会发生一个运行异常,因为把它强制转换为int时会失败。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleApplication8
    {
        class Program
        {
            static void Main(string[] args)
            {
                var m_list1 = new LinkedList();
                m_list1.AddLast(2);
                m_list1.AddLast(3);
                m_list1.AddLast(4);
                m_list1.AddLast("Dead27");
    
                foreach (int i in m_list1)
                {
                    Console.WriteLine(i);
                }
    
                Console.ReadKey();
            }
        }
    }

      

      下面创建链表的泛型类版本。泛型类的定义与一般类类似,只是要使用泛型类声明。之后,泛型类型就可以在类中用作一个字段成员,或者方法的参数类型。LinkedListNode类用一个泛型类型T声明。属性Value的类型是T,而不是object。构造函数也变为可以接受T类型的对象。也可以返回和设置泛型类型,所以属性Next和Prev的类型是LinkedListNode<T>。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleApplication8
    {
        class LinkedListNode<T>
        {
            private T m_value;
            public T Value
            {
                get
                {
                    return m_value;
                }
                set
                {
                    m_value = value;
                }
            }
    
            public LinkedListNode(T _value)
            {
                this.m_value = _value;
            }
    
            public LinkedListNode<T> Next { get; internal set; }
    
    
            public LinkedListNode<T> Prev { get; internal set; }
            
            
        }
    }

      下面的代码把LinkedList类也改为泛型类。LinkedList<T>包含 LinkedListNode<T>元素。LinkedList中的类型T定义了类型T的属性First和Last。AddLast()方法现在接受类型T的参数,并实例化LinkedListNode<T>类型的对象。

      除了IEnumerable接口,还有一个泛型版本IEnumerable<T>。IEnumerable<T>派生自IEnumerable,添加了返回IEnumerable<T>的GetEnumerator()方法,LinkedList<T>实现泛型接口IEnumerable<T>。

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleApplication8
    {
        class LinkedList<T> : IEnumerable<T>
        {
            public LinkedListNode<T> First{ get; private set; }
    
            public LinkedListNode<T> Last { get; private set; }
    
            public LinkedListNode<T> AddLast(T _node)
            {
                var newNode = new LinkedListNode<T>(_node);
                if (First == null)
                {
                    First = newNode;
                    Last = First;
                }
                else
                {
                    LinkedListNode<T> pervious = Last;
                    Last.Next = newNode;
                    Last = newNode;
                    Last.Prev = pervious;
                }
    
                return newNode;
            }
    
            public IEnumerator<T> GetEnumerator()
            {
                LinkedListNode<T> current = First;
                while (current != null)
                {
                    yield return current.Value;
                    current = current.Next;
                }
            }
    
            IEnumerator IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }
        }
    }

      使用泛型LinkedList<T>,可以用int类型实例化它,且无须装箱操作。如果不使用AddList()方法传递int,就会出现一个编译错误。使用泛型IEnumerable<T>,foreach语句也是类型安全,如果foreach语句中的变量不是int,就会出现一个编译错误。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleApplication8
    {
        class Program
        {
            static void Main(string[] args)
            {
                var m_list1 = new LinkedList<int>();
                m_list1.AddLast(2);
                m_list1.AddLast(3);
                m_list1.AddLast(4);
    
                var m_list2 = new LinkedList<string>();
    
                m_list2.AddLast("Dead");
                m_list2.AddLast("27");
                m_list2.AddLast("!");
    
                foreach (int i in m_list1)
                {
                    Console.WriteLine(i);
                }
    
                foreach (string i in m_list2)
                {
                    Console.WriteLine(i);
                }
    
                Console.ReadKey();
            }
        }
    }

     

     

    Dean二十七
  • 相关阅读:
    给Debian安装Xfce桌面
    【兄弟连ThinkPHP】1、介绍和安装
    CROSS JOIN,NATURAL JOIN
    表的连接查询
    多表查询在数据量非常大的时候性能不好,慎用!
    伪列:Oracle显示查询结果前几条记录用rownum<=。去掉重复记录,保留最早录入记录:取出最小ROWID
    其他函数:值为NULL时的默认值NVL,DECODE
    转换函数TO_CHAR,TO_DATE,TO_NUMBER
    50-用Python监听鼠标和键盘事件
    49-Python 安装pythoncom库和pyHook
  • 原文地址:https://www.cnblogs.com/Dean27/p/6110579.html
Copyright © 2011-2022 走看看