This is kind of hard to explain, I hope my English is sufficient:
I have a class "A" which should maintain a list of objects of class "B" (like a private List). A consumer of class "A" should be able to add items to the list. After the items are added to the list, the consumer should not be able to modify them again, left alone that he should not be able to temper with the list itself (add or remove items). But he should be able to enumerate the items in the list and get their values. Is there a pattern for it? How would you do that?
If the question is not clear enough, please let me know.
To prevent editing the list or its items you have to make them immutable, which means you have to return a new instance of an element on every request.
See Eric Lippert's excellent series of "Immutability in C#": http://blogs.msdn.com/ericlippert/archive/tags/Immutability/C_2300_/default.aspx (you have to scroll down a bit)
As many of these answers show, there are many ways to make the collection itself immutable.
It takes more effort to keep the members of the collection immutable. One possibility is to use a facade/proxy (sorry for the lack of brevity):
class B
{
public B(int data)
{
this.data = data;
}
public int data
{
get { return privateData; }
set { privateData = value; }
}
private int privateData;
}
class ProxyB
{
public ProxyB(B b)
{
actual = b;
}
public int data
{
get { return actual.data; }
}
private B actual;
}
class A : IEnumerable<ProxyB>
{
private List<B> bList = new List<B>();
class ProxyEnumerator : IEnumerator<ProxyB>
{
private IEnumerator<B> b_enum;
public ProxyEnumerator(IEnumerator<B> benum)
{
b_enum = benum;
}
public bool MoveNext()
{
return b_enum.MoveNext();
}
public ProxyB Current
{
get { return new ProxyB(b_enum.Current); }
}
Object IEnumerator.Current
{
get { return this.Current; }
}
public void Reset()
{
b_enum.Reset();
}
public void Dispose()
{
b_enum.Dispose();
}
}
public void AddB(B b) { bList.Add(b); }
public IEnumerator<ProxyB> GetEnumerator()
{
return new ProxyEnumerator(bList.GetEnumerator());
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
The downside of this solution is that the caller will be iterating over a collection of ProxyB objects, rather than the B objects they added.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With