Рассматривать:
enum Foo
{
Bar,
Quux,
}
void Main()
{
var enumValues = new[] { Foo.Bar, Foo.Quux, };
Console.WriteLine(enumValues.GetType()); // output: Foo[]
Console.WriteLine(enumValues.First().GetType()); // output: Foo
var intValues = enumValues.Cast<int>();
Console.WriteLine(intValues.GetType()); // output: Foo[] ???
Console.WriteLine(intValues.First().GetType()); // output: Int32
Console.WriteLine(ReferenceEquals(enumValues, intValues)); // true
var intValuesArray = intValues.ToArray();
Console.WriteLine(intValuesArray.GetType()); // output: Int32[]
Console.WriteLine(intValuesArray.First().GetType()); // output: Int32
Console.WriteLine(ReferenceEquals(intValues, intValuesArray)); // false
}
Обратите внимание на третий Console.WriteLine
- я ожидаю, что он напечатает тип, к которому преобразуется массив (Int32[]
), но вместо этого он печатает исходный тип (Foo[]
)! И ReferenceEquals
подтверждает, что действительно, первый вызов Cast<int>
по сути является no-op.
Поэтому я заглянул в источник Enumerable.Cast
и обнаружил следующее:
public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source)
{
IEnumerable<TResult> typedSource = source as IEnumerable<TResult>;
if (typedSource != null) return typedSource;
if (source == null) throw Error.ArgumentNull("source");
return CastIterator<TResult>(source);
}
Для наших намерений и целей единственное, что имеет значение, - это первые две строки, потому что они единственные, кого вызывают. Это означает, что строка:
var intValues = enumValues.Cast<int>();
эффективно переводится на:
var intValues = ((IEnumerable)enumValues) as IEnumerable<int>;
Однако удаление приведения к неуниверсальному IEnumerable
вызывает ошибку компилятора:
var intValues = enumValues as IEnumerable<int>; // error
Я ломал голову над тем, почему это так, и я думаю, что это связано с тем фактом, что Array
реализует неуниверсальный IEnumerable
и что в С# есть все виды специальных оболочек для массивов, но я, честно говоря, Точно сказать не могу. Может кто-нибудь объяснить мне, что здесь происходит и почему?