开发者

Readonly wrapper of a LinkedList. HowTo?

.NET v2

When the List has a very useful (4 me) method AsReadOnly() the LinkedList does not have su开发者_开发问答ch a method.

Is there a way to "quickly" interface an internal LinkedList to read only from the external code?


Why not just return a IEnumerable<T>? If you just want to let users enumerate the list without modifying it*, IEnumerable is the obvious choice.

If you want to have a read only interface of the LinkedList interface, you can wrap LinkedList, forward read only methods to the wrapped list and deny any changes.

*) Keep in mind that neither ReadOnlyCollection not IEnumerable will prevent callers to change state of objects in case of a collection of reference types. If the objects should be read only as well, you need to implement this as part of their type.


ReadOnlyCollection<T> takes an IList<T> as argument to the constructor. LinkedList<T> does not implement this interface. List<T> has a constructor overload that takes an IEnumerable<T> as argument, and LinkedList<T> implements this interface. So the following should work:

LinkedList<int> linked = new LinkedList<int>();
// populate the list

ReadOnlyCollection<int> readOnly = new ReadOnlyCollection<int>(
    new List<int>(linked));

It uses an instance of List<T> to carry the items into the ReadOnlyCollection<T> constructor.


#1 Fix the Linked List

class FixedLinkedList<T> : LinkedList<T>, IList<T>
{
    public T this[int index]
    {
        get
        {
            return GetAt(index).Value;
        }
        set
        {
            GetAt(index).Value = value;
        }
    }

    public int IndexOf(T item)
    {
        int i = 0;
        var node = First;
        while (node!= null && !node.Value.Equals(item))
        {
            i++;
            node = node.Next;
        }

        if (node == null)
        {
            return -1;
        }

        return i;
    }

    public void Insert(int index, T item)
    {
        AddBefore(GetAt(index), new LinkedListNode<T>(item));
    }


    public void RemoveAt(int index)
    {
        Remove(GetAt(index));
    }

    private LinkedListNode<T> GetAt(int index)
    {
        CheckIndex(index);
        int i = 0;
        var node = First;
        while (i < index)
        {
            i++;
            node = node.Next;
        }

        return node;
    }

    private void CheckIndex(int index)
    {
        if (index < 0)
        {
            throw new ArgumentOutOfRangeException(
                nameof(index),
                "Parameter must be greater or equal to 0.");
        }

        if (index >= Count)
        {
            throw new ArgumentOutOfRangeException(
                nameof(index),
                "Parameter must be lower than the list item Count.");
        }
    }
}

#2 Wraps its instances in ReadOnlyCollection


LinkedList<T> doesn't implement IList so in short, no there is no way of quickly doing it. If you cast your LinkedList to a List you will probably lose the functionality you require.

LinkedList<T> doesn't offer you anything for subclassing so you'll need to write your own. I imagine the next request is "can you show me how to do that"

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜