2015-04-19 3 views
-1

Недавно я начал проект хобби, чтобы переписать структуру коллекций, начиная с удаления не общего IEnumerator и IEnumerable, создавая новые базовые интерфейсы IEnumerator/IEnumerable. У меня быстро возникла проблема с выходом при создании преобразования между моим новым перечислимым интерфейсом и обычным.выход не работает с пользовательским перечисляемым/перечислителем

Мои IEnumerable<T> и IEnumerator<T> точно такие же, как и обычные, за исключением того, что они не наследуются от не общих. Почему урожайность не работает с моими интерфейсами? foreach действительно работает с моими интерфейсами.

Пример:

public static System.Collections.Generic.IEnumerable<T> ToMSEnumerable(this My.IEnumerable<T> enumerable) 
{ 
    foreach (var item in enumerable) // enumerating my enumerable works 
    { 
     yield return item; // this works 
    } 
} 

public static My.IEnumerable<T> ToMyEnumerable(this System.Collections.Generic.IEnumerable<T> enumerable) 
{ 
    foreach (var item in enumerable) // obviously work 
    { 
     yield return item; // this is where its not working. 
          // I haven't touched this in a few day, so I don't remember 
          // the error message 
    } 
} 
+0

Мне любопытно - что делает ваш 'My.IEnumerable ' делать иначе, чем стандартный 'IEnumerable '? – Enigmativity

+0

@Enigmativity У него нет универсального 'GetEnumerator()' – gbieging

+0

И почему это так важно? – Enigmativity

ответ

7

Ваши foreach работает, потому что foreach uses duck-typing - нибудь с методом GetEnumerator будет работать. Это связано с тем, что foreach старше дженериков, поэтому это был единственный разумный способ его реализации и получить сильную типизацию.

Однако методы итераторов являются не старше дженериков, так yield был разработан с IEnumerable<T> в виду. Поэтому yieldтребует:

  • Тип возвращаемого значения должен быть IEnumerable, IEnumerable<T>, IEnumerator или IEnumerator<T>.

(https://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx)

Естественно, что ваш дом построен перечислимы класс не в списке.

+1

На самом деле «классная» вещь для каждого - это тип 'GetEnumerator()' return не обязательно должен быть 'IEnumerator' all, It check for - это открытый метод с именем 'MoveNext()' и публичное свойство с именем 'Current', если у него есть две вещи, которые он с удовольствием будет работать. –

+0

Хороший ответ. Рассмотрите возможность редактирования вопроса для добавления правильного сообщения об ошибке, чтобы он не выглядел как кандидат для удаления. –

+0

Я представлял себе такое. Но кажется немного несовместимым с остальной частью «утиной печати» вокруг коллекций. – gbieging

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