在我的winform应用程序中使用LinkedList代替List

时间:2014-01-08 09:49:42

标签: c# winforms list linked-list

目前我的代码中有以下列表。

private List<myClass> mylist;

我可以用

替换它吗?
private LinkedList<myClass> mylist;

目标是当mylist的大小扩展到一定大小(比方说10)时,我从列表中删除最旧的条目并添加最新的条目,依此类推。显然LinkedList有以下我可以使用的方法(它们不在列表中)

mylist.RemoveFirst();

mylist.AddLast(..);

所以我的问题是,如果我从List更改为LinkedList,是否会丢失任何功能?我的意思是我的代码中依赖于List的其他东西会受到影响,或者就像这样你用List做什么,你也可以用LInkedList做到这一点?

其次,或者没有必要改为LinkedList。我的目标是实现我能用List吗?

(如果我使用List来实现我的目标

,我正在思考这些问题
if (mylist.Count >= maxNumEntries)
{
    list.RemoveAt(0);
}

list.Add(..);

由于

2 个答案:

答案 0 :(得分:1)

我的建议是,无需将List更改为LinkedList。它可能会也可能不会产生混淆,具体取决于您的代码。而且,你可以很容易地使用LINQ来制作这些简单的方法 我举一个下面这种方法的例子: -

您可以自定义RemoveFirst方法: -

    List<T> RemoveFirst(List<T> paramList)
    {
       List<T> tempList = paramList.Skip(1).ToList() ;
       return tempList ;
    }  

同样,您可以使用其他方法来操纵List<T>

用法

    List<int> myList = new List<int> () ; 
    // add some items to list 
    // now remove the first item. 
     myList = RemoveFirst(myList) ; 

选择DataStructure
List<T>LinkedList<T>不仅在它们提供的自定义方法中有所不同,而且在实现方面也有所不同 例如
LinkedList<T>相比,List<T>提供了对元素的较慢访问权限 我相信LinkedList<T>也有许多优势,但优秀的程序员会根据他们提供的属性选择数据结构。
在您的情况下,循环队列也很有用。 因此,请选择数据结构,而不是基于它们提供的方法,而是选择您认为对您的应用程序非常重要的属性。

答案 1 :(得分:0)

您似乎想要一个循环缓冲区(也称为环形缓冲区)。

您可能最好只编写一个自定义类来实现它,例如:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;

namespace Demo
{
    public class CircularBuffer<T>: IEnumerable<T>
    {
        /// <summary>Constructor.</summary>
        /// <param name="capacity">The maximum capacity of the buffer.</param>

        public CircularBuffer(int capacity)
        {
            // The reason for this +1 is to simplify the logic - we can use "front == back" to indicate an empty buffer.

            _buffer = new T[capacity+1];
        }

        /// <summary>The buffer capacity.</summary>

        public int Capacity
        {
            get
            {
                return _buffer.Length - 1;
            }
        }

        /// <summary>The number of elements currently stored in the buffer.</summary>

        public int Count
        {
            get
            {
                int result = _back - _front;

                if (result < 0)
                    result += _buffer.Length;

                return result;
            }
        }

        /// <summary>Is the buffer empty?</summary>

        public bool IsEmpty
        {
            get
            {
                return this.Count == 0;
            }
        }

        /// <summary>Is the buffer full? (i.e. has it reached its capacity?)</summary>

        public bool IsFull
        {
            get
            {
                return nextSlot(_back) == _front;
            }
        }

        /// <summary>Empties the buffer.</summary>

        public void Empty()
        {
            _front = _back = 0;
            Array.Clear(_buffer, 0, _buffer.Length); // Destroy any old references so they can be GCed.
        }

        /// <summary>Add an element to the buffer, overwriting the oldest element if the buffer is full.</summary>
        /// <param name="newItem">The element to add.</param>

        public void Add(T newItem)
        {
            _buffer[_back] = newItem;
            _back = nextSlot(_back);

            if (_back == _front) // Buffer is full?
            {
                _front = nextSlot(_front); // Bump the front, overwriting the current front.
                _buffer[_back] = default(T); // Remove the old front value.
            }
        }

        /// <summary>
        /// The typesafe enumerator. Elements are returned in oldest to newest order.
        /// This is not threadsafe, so if you are enumerating the buffer while another thread is changing it you will run
        /// into threading problems. Therefore you must use your own locking scheme to avoid the problem.
        /// </summary>

        public IEnumerator<T> GetEnumerator()
        {
            for (int i = _front; i != _back; i = nextSlot(i))
                yield return _buffer[i];
        }

        /// <summary>The non-typesafe enumerator.</summary>

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator(); // Implement in terms of the typesafe enumerator.
        }

        /// <summary>Calculates the index of the slot following the specified one, wrapping if necessary.</summary>

        private int nextSlot(int slot)
        {
            return (slot + 1) % _buffer.Length;
        }

        /// <summary>
        /// The index of the element at the front of the buffer. 
        /// If this equals _back, the buffer is empty.
        /// </summary>

        private int _front;

        /// <summary>
        /// The index of the first element BEYOND the last used element of the buffer. 
        /// Therefore this indicates where the next added element will go.
        /// </summary>

        private int _back;

        /// <summary>The underlying buffer. This has a length one greater than the actual capacity.</summary>

        private readonly T[] _buffer;
    }

    internal class Program
    {
        private void run()
        {
            CircularBuffer<int> buffer = new CircularBuffer<int>(10);

            for (int i = 0; i < 20; ++i)
                buffer.Add(i);

            foreach (int n in buffer)
                Console.WriteLine(n);  // Prints 10..19
        }

        private static void Main()
        {
            new Program().run();
        }
    }
}