Интереса ради начал изучать внутреннее устройство foreach
.
Наткнулся на такой паттерн, который создан, чтобы была совместимость из старого кода:
class Test : IEnumerable<T>
{
public IEnumerable<T> GetEnumerator()
{
}
IEnumerator IEnumerable.GetEnumerator()
{
}
}
Так как мы реализуем generic
интерфейс, то должны реализовать и методы из IEnumerable
, так как generic
интерфейс наследует его.
Как я понял, при написании обычного foreach
в текущих версиях языка, будет вызван неявный метод (который первый), исходя из понятия утиной типизации.
Вопрос: почему в старых версиях языка (до generic
'ов) будет вызван метод с явной реализацией?
Возможно, там такая реализация (с привидением к non-generic
интерфейсу)?
IEnumerator enumerator = ((IEnumerable)TestInstance).GetEnumerator();
...
Или я что-то неправильно понимаю?
Вы задаёте вопрос о C# 1.x, поскольку начиная с версии 2.0 C# уже содержит обобщения.
Посмотрим на спецификацию C# 1.0. Нас интересует раздел 8.8.4 The foreach statement. Согласно этому разделу, используется следующая последовательность проверок:
GetEnumerator
, возвращающий объект, обладающий методом MoveNext
и свойством Current
), то используется этот паттерн (даже если интерфейс IEnumerable
тоже поддерживается).IEnumerable
, то он используется.В вашем случае, когда метод IEnumerable.GetEnumerator()
объявлен через явную имплементацию интерфейса, первое условие не выполняется: метод IEnumerable.GetEnumerator
не публичный. (А метода public IEnumerable<T> GetEnumerator()
вовсе нет, раз наша версия языка не поддерживает обобщения.) Поэтому работает второе условие.
Кстати, в современных версиях языка просто перед второй проверкой выполняется дополнительная проверка на обобщённый IEnumerable<T>
. Но на первом месте в любом случае «утиная» проверка.
Виртуальный выделенный сервер (VDS) становится отличным выбором
Зачем сделали разные способы сохранения сериализированных данных? Например зачем нам сериализация в формате XML или SOAP или Бинарная сериализацияЕсли...
В предыдущих вопросах, я спрашивал про строки, сейчам появилась нужда удалить все строки, равны или нет, не важно, но чтобы оставить одну
Есть коллекция объектов, необходимо удалить из неё некоторые объекты отвечающие условиям (Например если свойство коллекции ID=5 то все объекты...
Как создать в классе список, который имеет несколько значений? Грубо говоря, сделать что-то, на подобие: