in my C#-project, I have a class which contains a List
public class MyClass
{
public MyClass parent;
public List children;
...
}
Expose the list as IEnumerable<MyClass>
If you hand the caller the List<T>
, you can't control this; you can't even subclass List<T>
, since the add/remove are not virtual
.
Instead, then, I would expose the data as IEnumerable<MyClass>
:
private readonly List<MyClass> children = new List<MyClass>();
public void AddChild(MyClass child) {...}
public void RemoveChild(MyClass child) {...}
public IEnumerable<MyClass> Children {
get {
foreach(var child in children) yield return child;
}
}
(the yield return
prevents them just casting it)
The caller can still use foreach
on .Children
, and thanks to LINQ they can do all the other fun things too (Where
, First
, etc).
Make the list private, and create public methods to access its content from outside the class.
public class MyClass
{
public MyClass Parent { get; private set; }
private List<MyClass> _children = new List<MyClass>();
public IEnumerable<MyClass> Children
{
get
{
// Using an iterator so that client code can't access the underlying list
foreach(var child in _children)
{
yield return child;
}
}
}
public void AddChild(MyClass child)
{
child.Parent = this;
_children.Add(child);
}
public void RemoveChild(MyClass child)
{
_children.Remove(child);
child.Parent = null;
}
}
By the way, avoid declaring public fields, because you can't control what client code does with them.
Use List(T).AsReadOnly()
.
http://msdn.microsoft.com/en-us/library/e78dcd75.aspx
Returns a read-only IList<(Of <(T>)>) wrapper for the current collection.
Available since .NET 2.0.
You don't need to reimplemented IList, just encapsulate a List in a class, and provide your own Add and Delete functions, that will take care of adding and setting the required properties.
You might have to create your own enumerator if you want to enumerate through the list though.
using System.Collections.ObjectModel;
public class MyClass
{
private List<MyClass> children;
public ReadOnlyCollection<MyClass> Children
{
get
{
return new ReadOnlyCollection<MyClass>(children);
}
}
}