2012-03-20 1 views
5

Можно создать дубликат:
IEnumerable.Cast<>Конвертировать int [] в double [] с помощью Cast <T>?

можно неявно преобразовать из междунар удвоить. Почему «Указанный приказ недействителен». здесь возникает исключение?

double[] a = Enumerable.Range(0, 7).Cast<double>().ToArray(); 

Я пробовал несколько «версий» этого.

P.S. Я знаю возможные решения, такие как:

double[] a = Enumerable.Range(0, 7).Select(x => (double)x).ToArray(); 

Но мне любопытно, как Cast works => почему это не работает в этом примере, который выглядит настолько очевидным.

ответ

4

Cast сделано для превращения IEnumerable (нетипизированного) в IEnumerable<T> (в типичном виде). На самом деле это не будет иначе - бросить кого-либо из членов.

Per this answer:

Ну, неверные ожидания Cast, что все - это означало иметь дело с боксом/распаковкой, справочные и идентификационных преобразованиями, и это все. Очень жаль, что документация не ясно, как это может быть

Итак, вы застряли с .Select().

+0

В свете этого, как «литой» 'int x = 42; double d = (double) x; 'work? –

+3

Не было бы более целесообразным закрыть этот вопрос как дубликат вместо того, чтобы предоставить принятый ответ из вопроса, на который вы ссылаетесь? –

+0

+1 Btw: выбор быстрее, чем Cast, проверял его несколько раз. –

3

Причина это не удается, потому что по существу вы делаете это:

 int x = 10; 
     object f = x; 
     double d = (double) f; 

ИНТ становится боксировал в объект, и когда вы идете распаковывать его, вы пытаетесь распаковывать его к двойной.

Более конкретно, вот реализация ролях:

public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source) 
{ 
    IEnumerable<TResult> enumerable = source as IEnumerable<TResult>; 
    if (enumerable != null) 
    { 
     return enumerable; 
    } 
    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)current; 
    } 
    yield break; 
} 

Как вы можете видеть, это зацикливание через IEnumerable и бокс каждого элемента в источнике. Затем он пытается распаковать, после чего вы взорваетесь.