There is one method in Lookup<,>
that is not in ILookup<,>
:
public IEnumerable<TResult> ApplyResultSelector<TResult>(
Func<TKey, IEnumerable<TElement>, TResult> resultSelector);
Why is the return type of Enumerable.ToLookup<>()
declared to be ILookup<,>
despite the fact that it always seems to return an instance of Lookup<,>
? If the return type were instead declared to be Lookup<,>
, the above method could be used without a cast.
The best practices for designing public APIs dictate that returning an interface is a better idea than returning a concrete class, because you can then return a different concrete class if you need to. The consumer of the API is not supposed to rely on the returned instance being of a specific type.
As you point out, ToList
and ToDictionary
return concrete types rather than interfaces. Perhaps the reason for this is that ToList
and ToDictionary
were meant to return you a copy that you can modify should you want to. Since the IList
and IDictionary
interfaces do not guarantee you that they are editable (which was possibly a bad idea), the designers decided to return the concrete type.
Imagine a hypothetical ToIList()
method. If called on an array, it could be implemented to return you a copy of the array, because arrays implement IList<T>
. You might then be surprised to find out that calling Add()
throws.
On the other hand, ILookup
is a read-only interface, so the above doesn't apply. Hence there is no reason not to follow the best practice, like there is with ToList
.
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