enum Gender { Male, Female }
var k = new[] { Gender.Male }.Cast().ToList().Cast().ToList(); //alright
var p = new[] { Gender.Male }.Cast<
Ok I have come to find out the cause, which is still strange. I should have checked up Cast<T>
implementation myself first of all!
This is how Cast<T>
is implemented:
public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source)
{
IEnumerable<TResult> enumerable = source as IEnumerable<TResult>;
if (enumerable != null)
{
return enumerable; // this is the culprit..
}
if (source == null)
{
throw Error.ArgumentNull("source");
}
return Enumerable.CastIterator<TResult>(source);
}
private static IEnumerable<TResult> CastIterator<TResult>(IEnumerable source)
{
foreach (object current in source)
{
yield return (TResult)((object)current);
}
yield break;
}
Now the problem is with the first Cast<int>
call:
new[] { Gender.Male }.Cast<int>()
Here source as IEnumerable<TResult>
where source
is new[] { Gender.Male }
and TResult
is int
in the generic method returns a non null value (which basically means (new[] { Gender.Male }
is an IEnumerable<int>
in generic context), and hence it returns the same enumerable back which is Gender[]
, and in the next Cast<int?>
call, the actual cast is performed, which is from Gender
to int?
which fails. As to why this happens in generic context, catch it in this question.
This is due to deferred execution. The latter statement actually tries to cast Gender.Male
to int?
. In contrast, the first statement actually performs the cast operation to an int
and gets a List<int>
before deferring the execution to cast those to int?
; clearly int
to int?
has an implicity conversion defined already.