How code can talk – Signatures and interfaces
I’ll start off with a small code sample. What could be read out of the signature of this method alone:
void DoSomething(IList<MyClass> list)
I intentionally chose a non-talking method name, because I want to elaborate on the parameters here, especially. So, “DoSomething” expects a parameter that implements the IList
void DoSomething(IList<MyClass> list)
{
foreach (MyClass item in list)
Console.WriteLine(item.Name);
}
Huh, interesting. Turns out I was wrong. No item is added, removed or inserted, nor is the list being cleared in there. But why is an IList
Custom interfaces
Of course it is the same with custom interfaces. Let’s say we have a class called “Repository” that implements the “IRepository” interface which, in turn, derives from “IReadOnlyRepository”. While the repository itself can store, update and get items, the read-only repository can only get items. Same as above applies: There is a lot being communicated if an IReadOnlyRepository is requested over an IRepository. We know, rather than assume, that data is only retrieved.
Casting
Don’t do this at home:
void DoSomething(IEnumerable<MyClass> list)
{
IList<MyClass> realList = (IList<MyClass>)list;
realList.Add(new MyClass());
}
While this compiles perfectly fine, this might result in runtime exceptions since we, the ones who wrote this method, can’t expect people to hand us something that is actually an IList, while we only tell them that we want an IEnumerable. Again, like above, this is about the communication through code. We tell the consumers of our method, that we will only iterate over the list provided, we don’t care if it is just an array or a list or even a dictionary. We simply cannot assume an IList is given us. Also the .Net 3.5 newly introduced “.ToList
Conclusion
Mainly for public interfaces – and all public methods of any class can be considered an interface unless hidden in another way, like having the class internal rather than public – it is very important to communicate your intentions. Don’t you want to be sure if you use this one method that expects a list, this list isn’t altered? Put yourself in the consumer’s mind. What would you think if you didn’t know the implementation but wanted to use it? At the same time, if you really need an IList, make sure any side effects – things that alter the list or how the list could be altered – are communicated in some other way. Be it comments, easily accessible documentations or, most preferably, the method name!