Я знаю, как реализовать не общий IEnumerable, например:
using System;
using System.Collections;
namespace ConsoleApplication33
{
class Program
{
static void Main(string[] args)
{
MyObjects myObjects = new MyObjects();
myObjects[0] = new MyObject() { Foo = "Hello", Bar = 1 };
myObjects[1] = new MyObject() { Foo = "World", Bar = 2 };
foreach (MyObject x in myObjects)
{
Console.WriteLine(x.Foo);
Console.WriteLine(x.Bar);
}
Console.ReadLine();
}
}
class MyObject
{
public string Foo { get; set; }
public int Bar { get; set; }
}
class MyObjects : IEnumerable
{
ArrayList mylist = new ArrayList();
public MyObject this[int index]
{
get { return (MyObject)mylist[index]; }
set { mylist.Insert(index, value); }
}
IEnumerator IEnumerable.GetEnumerator()
{
return mylist.GetEnumerator();
}
}
}
Однако я также заметил, что IEnumerable имеет общую версию IEnumerable<T>
, но я не могу понять, как ее реализовать.
Если я добавлю using System.Collections.Generic;
к своим директивам using, а затем изменю:
class MyObjects : IEnumerable
чтобы:
class MyObjects : IEnumerable<MyObject>
Затем щелкните правой кнопкой мыши IEnumerable<MyObject>
и выберите Implement Interface => Implement Interface
, Visual Studio услужливо добавляет следующий блок кода:
IEnumerator<MyObject> IEnumerable<MyObject>.GetEnumerator()
{
throw new NotImplementedException();
}
Возврат неуниверсального объекта IEnumerable из GetEnumerator();
метода на этот раз не сработает, так что мне здесь указать? Интерфейс командной строки теперь игнорирует неуниверсальную реализацию и направляется прямо к общей версии, когда пытается выполнить перечисление через мой массив во время цикла foreach.
this.GetEnumerator()
и простым возвратом в неуниверсальной реализацииGetEnumerator()
?Collection<MyObject>
и тогда вам не придется писать какой-либо собственный код.List<T>
и реализовать,IEnumerable<T>
как показано в вашем ответе.Вероятно, вам не нужна явная реализация
IEnumerable<T>
(что вы показали).Обычный шаблон - использовать
IEnumerable<T>
'sGetEnumerator
в явной реализацииIEnumerable
:источник
IEnumerable
избыточна (IEnumerable<T>
уже наследуется от нее).Почему вы делаете это вручную?
yield return
автоматизирует весь процесс обработки итераторов. (Я также писал об этом в своем блоге , включая просмотр кода, созданного компилятором).Если вы действительно хотите сделать это самостоятельно, вам также нужно вернуть универсальный перечислитель. Вы не сможете больше использовать,
ArrayList
поскольку это не общий.List<MyObject>
Вместо этого замените его на . Это, конечно, предполагает, чтоMyObject
в вашей коллекции есть только объекты типа (или производных типов).источник
yield return
. Я ошибочно предположил, что была некоторая нестандартная обработка.Если вы работаете с универсальными шаблонами, используйте List вместо ArrayList. В List есть именно тот метод GetEnumerator, который вам нужен.
источник
превратить мой список в
List<MyObject>
, это один из вариантовисточник
Обратите внимание, что все
IEnumerable<T>
уже реализовано,System.Collections
поэтому другой подход заключается в наследовании вашегоMyObjects
классаSystem.Collections
как базового класса ( документация ):Мы можем позже сделать наши собственные реализации внешним переопределить виртуальные
System.Collections
методы , чтобы обеспечить пользовательское поведение (только дляClearItems
,InsertItem
,RemoveItem
иSetItem
вместе сEquals
,GetHashCode
иToString
сObject
). В отличие от,List<T>
который не предназначен для легкого расширения.Пример:
Обратите внимание, что движение от
collection
рекомендовано только в том случае, если требуется настраиваемое поведение сбора, что случается редко. см. использование .источник