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"
精彩评论