【读书笔记】创建泛型编程类 由链表而深入

首先看下一个一般的,非泛型的简化链表类。

using System;
using System.Collections;
using System.Linq;
using System.Text;

// 不要使用System.Collections.Generic命名空间
// 使用System.Collections命名空间
// 否则当继承 IEnumerable类的时候,会有错误发生

/*-----------------------------------------------------------------------
 * 创建泛型类实例
 * 作者: Herbert
 * ----------------------------------------------------------------------
 */

namespace Generic
{
    // 定义一个链表节点 
    // 包含一个节点,节点带有一个value值
    // 同时包含上一个节点和下一个节点的引用
    public class LinkedListNode
    {
        private object value;

        public LinkedListNode(object value)
        {
            this.value = value;
        }

        public object Value
        {
            get
            {
                return value;
            }
        }

        private LinkedListNode next;
        public LinkedListNode Next
        {
            get
            {
                return next;
            }
            internal set
            {
                next = value;
            }
        }

        private LinkedListNode prev;
        public LinkedListNode Prev
        {
            get
            {
                return prev;
            }
            internal set
            {
                prev = value;
            }
        }
    }


    // 定义链表类
    // 链表类包含及诶单类型的first和last字段,标记链表的头尾    
    class LinkedList : IEnumerable
    {
        private LinkedListNode first;
        public LinkedListNode First
        {
            get
            {
                return first;
            }
        }

        private LinkedListNode last;
        public LinkedListNode Last
        {
            get
            {
                return last;
            }
        }

        public LinkedListNode AddLast(object node)
        {
            LinkedListNode newNode = new LinkedListNode(node);

            // AddLast()方法在链表尾添加一个新元素。首先创建创建一个LinkedListNode类型的对象。如果链表是空的,则first和last字段就设置为该新元素
            // 否则就把新元素添加为链表中的最后一个元素
            if (first == null)
            {
                first = newNode;
                last = first;
            }
            else
            {
                last.Next = newNode;
                last = newNode;
            }
            return newNode;
        }

        public IEnumerator GetEnumerator()
        {
            LinkedListNode current = first;
            while (current != null)
            {
                yield return current.Value;
                current = current.Next;
            }
        }
    }


}

 

下面这个是运行的main方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Generic
{
    class Program
    {
        static void Main(string[] args)
        {
            LinkedList list1 = new LinkedList();
            list1.AddLast(2);
            list1.AddLast(4);

            // The casting from string to int is invalid
            //list1.AddLast("6"); 

            foreach (int i in list1)
            {
                Console.WriteLine(i);               
            }

            Console.ReadLine();
        }
    }
}

 

这个里面的//list1.AddLast("6"); 是非法的,因为.NET似乎不能自动把字符串转化为int类型。那样的话,int i in list1这句话就要报错了。

 

下面看泛型后的链表类:

 

using System;
using System.Collections;
using System.Linq;
using System.Text;
using System.Collections.Generic;


/*-----------------------------------------------------------------------
 * 创建泛型类实例
 * 作者: Herbert
 * 网址: http://www.cnblogs.com/herbert
 * ----------------------------------------------------------------------
 */

namespace Generic
{
    // 定义一个链表节点 
    // 包含一个节点,节点带有一个value值
    // 同时包含上一个节点和下一个节点的引用
    public class LinkedListNode<T>
    {
        private T value;

        public LinkedListNode(T value)
        {
            this.value = value;
        }

        public T Value
        {
            get
            {
                return value;
            }
        }

        private LinkedListNode<T> next;
        public LinkedListNode<T> Next
        {
            get
            {
                return next;
            }
            internal set
            {
                next = value;
            }
        }

        private LinkedListNode<T> prev;
        public LinkedListNode<T> Prev
        {
            get
            {
                return prev;
            }
            internal set
            {
                prev = value;
            }
        }
    }


    // 定义链表类
    // 链表类包含及诶单类型的first和last字段,标记链表的头尾    
    public class LinkedList<T> : IEnumerable<T>
    {
        private LinkedListNode<T> first;
        public LinkedListNode<T> First
        {
            get
            {
                return first;
            }
        }

        private LinkedListNode<T> last;
        public LinkedListNode<T> Last
        {
            get
            {
                return last;
            }
        }

        public LinkedListNode<T> AddLast(T node)
        {
            LinkedListNode<T> newNode = new LinkedListNode<T>(node);

            // AddLast()方法在链表尾添加一个新元素。首先创建创建一个LinkedListNode类型的对象。如果链表是空的,则first和last字段就设置为该新元素
            // 否则就把新元素添加为链表中的最后一个元素
            if (first == null)
            {
                first = newNode;
                last = first;
            }
            else
            {
                last.Next = newNode;
                last = newNode;
            }
            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();
        }        
    }
}

 

运行的Main函数

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Generic
{
    class Program
    {
        static void Main(string[] args)
        {
            LinkedList<int> list1 = new LinkedList<int>();
            list1.AddLast(1);
            list1.AddLast(3);
            list1.AddLast(5);

            foreach (int i in list1)
            {
                Console.WriteLine(i);               
            }

            Console.ReadLine();
        }
    }
}

 

这里面需要注意IEnumberable 有 泛型和非泛型两者用途,对应的使用的时候,加上适当的命名空间。不然会编译报错。

 

First you have to understand that IEnumberable has both generic and not-generic usage.  That was my problem.  In my code, I included the using System.Collections; namespace and in my code I was doing the following:

 IEnumerable <test_order> orders = db.getOrdersByCustomer(1);

Where test_order was type produced with a Linq to Sql Class and getOrdersByCustomer was a Stored Procedure. 

 

I kept getting the error:

The non-generic type 'System.Collections.IEnumerable' cannot be used with type arguments 

 

Which basically told me my problem, but I was too blind to see it at first.  Since I was just calling the System.Collections.IEnumerable, and not the System.Collections.Generic.IEnumerable, I was not allowing the use of generics; hence the error.  Simple add the following to you code and you will not have this error any longer: 

using System.Collections.Generic;
posted @ 2010-05-21 15:31  类型安全的心  阅读(516)  评论(0编辑  收藏  举报