通用链接列表

时间:2010-06-30 14:48:42

标签: c# generics

在发布我的问题之前,我想告诉你我以前没有.Net技术的经验,并且最近开始学习C#(和WPF)。我的公司正在寻求转向.Net技术,我是我团队中唯一一个学习它的人,所以除了你们之外没有人讨论或询问过什么。因此,如果我的问题太愚蠢或最基本,请耐心等待。

我试图创建一个通用的链表类,以允许创建不同类型的链表。我编写了以下代码,并希望就是否正确编写此代码提出建议。任何以任何方式改进代码的建议都是受欢迎的。

主程序

class Program
{
    static void Main(string[] args)
    {
        GenLinkedList<string> list = new GenLinkedList<string>("abc");
        list.AddtoList("def");
        int i = 0;
        string[] arr = new string[10];
        list.LinkedList.CopyTo(arr,0);
        for (i = 0; i < list.LinkedList.Count; i++)
        {
            Console.WriteLine(arr[i]);
        }

        GenLinkedList<int> listInt = new GenLinkedList<int>(1);
        listInt.AddtoList(2);
        i = 0;
        int[] arrInt = new int[10];
        listInt.LinkedList.CopyTo(arrInt, 0);
        for (i = 0; i < listInt.LinkedList.Count; i++)
        {
            Console.WriteLine(arrInt[i]);
        }

    }
}

班级GenLinkedList

public class GenLinkedList<T>
{
    private LinkedList<T> _linkedlist;
    public GenLinkedList(T a)
    {
        _linkedlist = new LinkedList<T>();
        _linkedlist.AddLast(a);
    }

    public LinkedList<T> LinkedList
    {
        get
        {
            return _linkedlist;
        }
    }

    public void AddtoList(T a)
    {
        LinkedList.AddLast(a);
    }
}

4 个答案:

答案 0 :(得分:7)

为什么不使用System.Collections.Generic.LinkedList<T>?您已在GenLinkedList<T>内部使用它,它已经是您的通用。

这是框架提供的通用双链表实现。请阅读:

MSDN - LinkedList(T) Class

如果您要创建通用链接列表作为练习,则不应基于现有通用链接列表的实现。你真的不会通过包装已经完全符合你需要的东西来学习任何东西。

答案 1 :(得分:3)

1

.NET框架中已存在通用链表实现:LinkedList<T>。但你已经知道了;你的代码包装它。

2

好的,所以你知道。那么你为什么要把它包起来呢?您似乎实现的唯一功能是AddtoListLinkedList<T>没有执行任何操作(毕竟,这只是LinkedList<T>.AddLast周围的一个薄包装) 。这意味着您的GenLinkedList<T> 提供链表的功能;它基本上是一个只添加的集合(可以很容易地使用List<T>Stack<T>Queue<T>实现 - 真的是任何东西。

3

假设你有充分的理由来包装LinkedList<T>(例如,你计划在线上添加更多功能,实际上会利用{{1}的行为} 和/或 - 这是一个关键因素 - 你希望限制调用代码能够与列表交互的方式(例如,没有删除)),你真的不应该暴露你的LinkedList<T>成员。包装器的目的就是:包装。你拿一个现有的类,基本上给它一种新的界面。通过直接暴露底层对象,可以削弱包装器。您可以绕过包装器中的任何其他限制/验证/逻辑。

因此,例如,如果您希望能够将列表复制到数组中,而不是这样做:

LinkedList<T>

您可以在list.LinkedList.CopyTo(arr,0); 课程中实施CopyTo方法(可以简单地调用GenLinkedList<T>)并使用该方法。

但我真的认为你应该问自己的第一个问题是你想要通过首先包装_linkedlist.CopyTo来实现的目标。

答案 2 :(得分:1)

显而易见的问题是,为什么你不直接使用LinkedList<T>,虽然看起来你正试图模仿一个单链表。

在这种情况下,您应该避免暴露底层的LinkedList<T>实例,因为任何客户端都可以直接操作它。我还会实现IEnumerable<T>,这将使你的列表可以被linq使用。

答案 3 :(得分:0)

我从http://msdn.microsoft.com/en-us/library/0x6a29h6.aspx得到了这个 对我很好。

namespace GenLinkedList
{
    class Program
    {
        static void Main(string[] args)
        {
            GenericList<object> list = new GenericList<object>();

            // Add items to list.
            list.AddHead("some string here");
            list.AddHead(DateTime.Today.ToLongDateString());
            list.AddHead(13);
            list.AddHead(13.005);
            for (int x = 0; x < 10; x++)
            {
                list.AddHead(x);
            }

            // Enumerate list.
            foreach (object i in list)
            {
                Console.WriteLine(i + " " + i.GetType());
            }
            Console.WriteLine("\nDone");
        }
    }
}

namespace GenLinkedList
{
    // type parameter T in angle brackets
    class GenericList<T>
    {
        // The nested class is also generic on T.
        public class Node
        {
            private Node next;

            // T as private member data type.
            private T data;


            // T used in non-generic constructor.
            public Node(T t)
            {
                next = null;
                data = t;
            }

            public Node Next
            {
                get { return next; }
                set { next = value; }
            }

            public T Data
            {
                get { return data; }
                set { data = value; }
            }
        }

        private Node head;

        // constructor
        public GenericList()
        {
            head = null;
        }

        // T as method parameter type
        public void AddHead(T t)
        {
            Node n = new Node(t);
            n.Next = head;
            head = n;
        }

        public IEnumerator<T> GetEnumerator()
        {
            Node current = head;

            while (current != null)
            {
                yield return current.Data;
                current = current.Next;
            }

        }
    }
}