Encapsulate Collection in C#


Today I was reading a great book by Martin Fowler "Refactoring: Improving the Design of Existing Code". This is a good chance for me to organize in my head and improve knowledge of good practices in coding. Even more, all code samples in the book are in Java, so I can note some interesting differences between .NET and Java.
Reading about pattern Encapsulate Field I was pretty proud for C# as it has 2 features I like very much: properties in common and auto-properties particularly, which turns about 10 lines of encapsulation for single field using methods (as in Java) to only one auto-property line.
Then I moved to chapter Encapsulate Collection. And it suddenly made me to meditate...

But let's be consistent. I described thoughts that confused me in StackOverflow question, and here is this it:

Since 3.0 C# has great syntax sugar like auto-properties which a lot simplify implementation of encapsulation principle. This is good if you use it with atomic values, so you can replace encapsulation pattern like this:
private string _name;
public string Name {
  get { return _name; }
  set { _name = value; }
}
with just one line:
public string FirstName  { get; set; }
I very like this great feature as it saves a lot of developers time.

But things are not so great when you create property that points to collection. Usually I see collection properties implemented in one of two ways.
1) Without auto-properties at all to be able to use field initializer:
private List<string> _names = new List<string>();
public List<string> Names
{
    get { return _names; }
}
2) Using auto-properties. This approach is ok if class has only one constructor:
public List<string> Names { get; private set; }
public .ctor()
{
    Names = new List<string>();
}
But when you deal with mutable collections like lists such a way, you break encapsulation, as user of this property can modify collection without letting container know (or even replace collection if you forget to make setter private).
As for me, regarding to Encapsulate Collection pattern correct implementation of collection encapsulation should look like this:
private readonly List<string> _names = new List<string>();
public ICollection<string> Names
{
    get { return new ReadOnlyCollection<string>(_names); }
}
public void Add_Name(string name)
{
    _names.Add(name);
}
public void Remove_Names(string name)
{
    _names.Remove(name);
}
public void Clear_Names()
{
    _names.Clear();
}
Honestly, I do not remember if I've met this kind of implementation in the real code, even in framework sources. I think this is because people are lazy and avoid writing such amount of code just to make encapsulation just a little bit stronger.
I wondering why C# team does not provide some clear and easy way to define collection auto-properties, so developers can please their laziness still creating robust code?

Certainly, first of all I've got a couple of useless answers from reputation hunters (here I need to say that pointing system of stackoverflow system is far from perfect, it simulates to make content, not knowledge, but this is a subject for another post).
Then I've got a nice note that returning read-only property as ICollection is not a good idea, as this interface has methods for modification of collection. When implementing ICollectionReadOnlyCollection hides those methods, and throws NotSupportedException if they are called explicitly through interface. So the best approach will be returning ReadOnlyCollection without any downcasting. BTW, do not be confused by name of this class, it is actually list, as it implements not only ICollection  but also IList.
Finally Justin wrote great answer that summarized controversies with collection encapsulation. First of all, he described that it is hard to predict how collection needs to be encapsulated. He picked up the following use cases for encapsulated collections:
1) A collection which can be changed.
2) A collection that can be modified, but not swapped.
3) Expose a read-only copy of a collection.
4) Collections that can be modified, but only in a certain way.
5) Custom implementation of collection.
So it is not enough to implement just one of them on compiler level. Maybe gyus from C# team could implement most used of them, however they have a lot of other interesting things to implement. You can always read about them in my favourite blog written by one of C# developers Eric Lippert.

Comments

  1. Really it was an awesome article...very interesting to read..You have provided an nice article....Thanks for sharing..
    Are you looking for the best Java training institute in Chennai?
    Come and learn with Aorta, the best java training institute in Chennai offering the best platform to learn and get the depth of Java
    java training in chennai
    java course in chennai

    ReplyDelete

Post a Comment