I typically try to follow a methodology of having arguments to methods be as generic as possible and return types as generic as necessary and have run into a problem to which the answer is not overly clear to me.
I have a control which operates on a structure like:
IDictionary<string, IDictionary<string, IEnumerable<MyObject>>>
So that supplying two keys, we get a collection of objects back. Pretty straight forward.
I have a class
ReadOnlyDictionary<TKey, TValue> : IDictionary<TKey, TValue>
which is just that, a readonly dictionary so that any IDictionary methods which would alter the dictionary throw an NotSupportedException();
The dictionary on which the control operates comes out of a MyObjectRepository which returns a
ReadOnlyDictionary<string, ReadOnlyDictionary<string, ReadOnlyCollection<MyObject>>>
So the question is, should I update the return type on my repository to return
IDictionary<string, IDictionary<string, IEnumerable<MyObject>>>
or ...? I don't think it would be correct to update the method to take a readonly dictionary as that is unnecessarily limiting.
It seems that this makes it less clear about the return type. Also, the interface defines the ReadOnlyDictionary as the return type so that implementing classes cannot return dictionaries which would allow modification. It just feels like if the interface is returning a collection which should be read only, then the return type should reflect that. By specifying the generic IDictionary<...> return type, methods which use the interface may try to modify the dictionary only to run into a NotSupportedException.
Any suggestions on how to resolve this are appreciated!
UPDATE As it turns out, the real issue here is with the ReadOnlyCollection. It simply should be replaced by IEnumerable and it simplifies much of the work converting between various return types.
See ReadOnlyCollection or IEnumerable for exposing member collections? and notice Jon Skeet's answer. This is why I love SO :)