Я хочу реализовать метод Cast
, потому что у меня есть тонны уродливых source.Select(x => type(x)).ToArray()
. Поэтому я пишу простое расширение:Ковариация для встроенных типов
public static IEnumerable<TResult> CastConvertible<TResult>(this IEnumerable<IConvertible> source)
{
foreach (var value in source)
{
yield return (TResult) Convert.ChangeType(value, typeof (TResult));
}
}
Но это не работает из-за ошибки:
Error CS1929 'IEnumerable< int>' does not contain a definition for 'CastConvertible' and the best extension method overload 'ZEnumerable.CastConvertible< short>(IEnumerable< IConvertible>)' requires a receiver of type 'IEnumerable< IConvertible>'
Но int
является IConvertible
в то время как мы знаем, что IEnumerable<out T>
ковариантен так IEnumerable<DerivedType>
могут быть преобразованы в IEnumerable<BaseType>
.
Вот пример:
int a = 10;
int[] b = {a};
IConvertible aa = a;
IEnumerable<IConvertible> bb = b;
Так что я должен удалить where
ограничение, чтобы иметь возможность использовать этот метод, но в этом случае я теряю время компиляции проверки, что тип может быть преобразован.
Почему ковариация в этом случае не работает?
Я не использую Enumerable.Cast<T>
, потому что он не работает для встроенных типов. Например, short[] shorts = new int[] {1, 2, 3}.Cast<short>().ToArray();
генерирует исключение, потому что метод Cast
использует внутренне не общий IEnumerable
, поэтому каждое значение помещается в квадрат, а затем генерирует исключение, потому что распаковка действительна только для точного начального типа.
Почему вы не используя 'IEnumerable.Cast'? –
Потому что он не работает в этом случае. Простой пример 'short [] shorts = new int [] {1,2,3} .Cast() .ToArray()' –
См. [This] (http: // stackoverflow.com/questions/445471/puzzling-enumerable-cast-invalidcastexception) thread –