Объясните,пожалуйста,почему в ниже приведенном коде возможен Upcast типа IEnumerator
static IEnumerator
static void Main(string[] args)
{
IEnumerable
//List
//foreach (var number in oddnumbers)
//{
// Console.WriteLine(number);
//}
//Console.ReadLine();
}
Ответ
Извините, неверно прочитал вопрос вначале, ответ полностью переписан.
Дело в том, что в C# любой объект можно закастить к любому интерфейсу на этапе компиляции:
interface I1 { }
class Program
{
static void Main(string[] args)
{
I1 i1 = (I1)(new Program());
}
}
В рантайме, если объект реально не имплементирует интерфейс, выбросится исключение InvalidCastExcetion
Почему же разрешён каст к интерфейсу, хотя объект на самом деле не имплементирует этот интерфейс? Рассмотрим код
Program p = new Program();
I1 i1 = (I1)p;
В этой точке статический тип выражения p, на которое навешен каст — Program. Но реальный, динамический тип может быть любой, производный от Program. И этот тип вполне может имплементировать интерфейс! Поэтому компилятор не может доказать, что каст невозможен, и откладывает проверку до момента реального выполнения.
Сравните:
interface I1 { }
sealed class Program // добавили sealed
{
static void Main(string[] args)
{
I1 i1 = (I1)(new Program()); // Не компилируется, ошибка CS0030
}
}
В этих условиях компилятор таки может доказать, что выражение не может имплементировать интерфейс, ведь класс Program этот интерфейс не имплементирует, а производных классов быть не может. Вот этот код и не компилируется.
Компилятор, конечно, мог бы быть суперумным, и увидеть, что выражение GetOddNumbers(...) есть вызов функции-генератора, и не имплементирует IEnumerable
Комментариев нет:
Отправить комментарий