views:

57

answers:

1

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.

+6  A: 

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.

romkyns
Well then surely `ToList` and `ToDictionary` are really badly designed.
Timwi
@Timwi Addressed that in an edit.
romkyns