2016-01-18 9 views
-2

Просто пытаюсь понять C#. Просто рассмотрим следующий упрощенный пример.Почему этот неявный листинг не приводит к ошибке времени компиляции?

void Main() 
{ 
    IList<IAnimal> animals = new List<IAnimal> 
    { 
     new Chicken(), 
     new Cow(), 
    }; 

    // Shouldn't this line result in a compile-time error? 
    foreach (Chicken element in animals) 
    { 
    } 
} 

public interface IAnimal 
{ 
} 

public class Cow : IAnimal 
{ 
} 

public class Chicken : IAnimal 
{ 
} 

Хотя первая итерация завершается успешно, вторая - нет. Честно говоря, я ожидал, что это не сработает во время компиляции. Кто-нибудь понимает, почему он только терпит неудачу во время выполнения?

+2

[Ответил Эрик Липперт] (http://ericlippert.com/2013/07/22/why-does-a-foreach-loop-silently-insert-an-explicit-conversion/) –

+0

Также см .: [ Почему цикл foreach молча вставляет «явное» преобразование?] (Http://ericlippert.com/2013/07/22/why-does-a-foreach-loop-silently-insert-an-explicit-conversion/) by Eric Lippert – Habib

+1

Не мог ли кто-нибудь связать сообщение Эрика Липперта об этом? – CodeCaster

ответ

5

Поскольку foreach оператор определен в C# Language Specification иметь (скрытый) явное приведение:

Вышеуказанные шаги, в случае успеха, однозначно производить тип коллекции C, тип перечислителя E и элемент типа T. Еогеасп утверждение вида

foreach (V v in x) embedded-statement 

затем расширен:

{ 
    E e = ((C)(x)).GetEnumerator(); 
    try { 
     while (e.MoveNext()) { 
      V v = (V)(T)e.Current; 
      embedded-statement 
     } 
    } 
    finally { 
     … // Dispose e 
    } 
} 

(Обратите внимание на (V)(T)e.Current, "Явный" преобразованный к типу V)

Он, к сожалению, определяется как это, потому что это то, что вы действительно необходимо в C# 1 (до дженериков, где каждая коллекция, которую вы хотите итерации в foreach, была сборкой object), и теперь для обратной совместимости ее нельзя изменить.

 Смежные вопросы

  • Нет связанных вопросов^_^