UPDATE: This question was the topic of my blog in July 2013 . Thanks for the great question!
You have found an unsuccessful edge case in the output method of a typical method. We have:
Distinct<X>(IEnumerable<X>, IEqualityComparer<X>)
where the interfaces are:
IEnumerable<out T> -- covariant
and
IEqualityComparer<in T> -- contravariant
When we conclude from allPositions to IEnumerable<X> , we say: " IEnumerable<T> covariant in T, so we can accept Position or any larger type (the base type is" larger "than the derived type, there are more animals in the world, than giraffes.)
When we conclude from the comparator, we say: " IEqualityComparer<T> is contravariant in T, so we can accept a BaseClass or any smaller type."
So what happens when the time comes to infer a type argument? We have two candidates: Position and BaseClass . Both satisfy the specified boundaries . Position satisfies the first estimate because it is identical to the first estimate and satisfies the second estimate because it is less than the second. BaseClass satisfies the first BaseClass because it is larger than the first grade and matches the second grade.
We have two winners. We need a switch. What are we doing in this situation?
This was the point of some debate, and there are arguments on three sides: choose more specific types, choose more general types, or don't let the type enter. I will not rephrase the whole argument, but suffice it to say that the “choose a more general” side won the day.
(To make matters worse, there is a typo in the specification saying that “choosing a more specific one” is the right thing! This was the result of an editing error during a design process that never fixed. The compiler implements “choosing a more general one.” I recalled Mads error and hopefully this will be fixed in the C # 5 spec.)
So you go. In this situation, the type inference selects a more general type and indicates that the call means Distinct<BaseClass> . Type inference never takes into account the type of the return value, and of course it does not accept what is assigned to this expression, so the fact that it selects a type that is incompatible with the assigned variable is not a business.
My advice is to explicitly specify a type argument in this case.