Как мне реализовать IEnumerable <T>
126420 просмотра
6 ответа
Я знаю, как реализовать не универсальный 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;
к своим директивам использования, а затем изменить:
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();
метода на этот раз не работает, так что мне здесь поставить? CLI теперь игнорирует неуниверсальную реализацию и направляется прямо к универсальной версии, когда он пытается перечислить через мой массив во время цикла foreach.
Ответы (6)
140 плюса
Если вы решите использовать универсальную коллекцию, например List<MyObject>
вместо ArrayList
, вы обнаружите, что она List<MyObject>
будет предоставлять как универсальные, так и неуниверсальные перечислители, которые вы можете использовать.
using System.Collections;
class MyObjects : IEnumerable<MyObject>
{
List<MyObject> mylist = new List<MyObject>();
public MyObject this[int index]
{
get { return mylist[index]; }
set { mylist.Insert(index, value); }
}
public IEnumerator<MyObject> GetEnumerator()
{
return mylist.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
Автор: Monroe Thomas
Размещён: 02.07.2012 03:45
61 плюса
Вы, вероятно, не хотите явной реализации IEnumerable<T>
(что вы показали).
Обычная картина для использования IEnumerable<T>
«S GetEnumerator
в явной реализации IEnumerable
:
class FooCollection : IEnumerable<Foo>, IEnumerable
{
SomeCollection<Foo> foos;
// Explicit for IEnumerable because weakly typed collections are Bad
System.Collections.IEnumerator IEnumerable.GetEnumerator()
{
// uses the strongly typed IEnumerable<T> implementation
return this.GetEnumerator();
}
// Normal implementation for IEnumerable<T>
IEnumerator<Foo> GetEnumerator()
{
foreach (Foo foo in this.foos)
{
yield return foo;
//nb: if SomeCollection is not strongly-typed use a cast:
// yield return (Foo)foo;
// Or better yet, switch to an internal collection which is
// strongly-typed. Such as List<T> or T[], your choice.
}
// or, as pointed out: return this.foos.GetEnumerator();
}
}
Автор: user7116
Размещён: 02.07.2012 03:41
24 плюса
Почему вы делаете это вручную? yield return
автоматизирует весь процесс обработки итераторов. (Я также написал об этом в своем блоге , в том числе посмотрите на код, сгенерированный компилятором).
Если вы действительно хотите сделать это самостоятельно, вам также нужно вернуть универсальный перечислитель. Вы не сможете использовать ArrayList
больше, поскольку это не является общим. Измените это List<MyObject>
вместо. Это, конечно, предполагает, что MyObject
в вашей коллекции есть только объекты типа (или производных типов).
4 плюса
Если вы работаете с дженериками, используйте List вместо ArrayList. В списке есть именно тот метод GetEnumerator, который вам нужен.
List<MyObject> myList = new List<MyObject>();
Автор: Amiram Korach
Размещён: 02.07.2012 03:42
0 плюса
0 плюса
Обратите внимание, что IEnumerable<T>
уже реализованный System.Collections
другой подход заключается в том, чтобы вывести ваш MyObjects
класс System.Collections
как базовый класс ( документация ):
System.Collections: Предоставляет базовый класс для универсальной коллекции.
Мы можем позже сделать наши собственные реализации внешним переопределить виртуальные System.Collections
методы , чтобы обеспечить пользовательское поведение (только для ClearItems
, InsertItem
, RemoveItem
и SetItem
вместе с Equals
, GetHashCode
и ToString
с Object
). В отличие от того, List<T>
который не предназначен для легкого расширения.
Пример:
public class FooCollection : System.Collections<Foo>
{
//...
protected override void InsertItem(int index, Foo newItem)
{
base.InsertItem(index, newItem);
Console.Write("An item was successfully inserted to MyCollection!");
}
}
public static void Main()
{
FooCollection fooCollection = new FooCollection();
fooCollection.Add(new Foo()); //OUTPUT: An item was successfully inserted to FooCollection!
}
Обращаем ваше внимание, что ехать из collection
рекомендованного автомобиля рекомендуется только в том случае, если необходимо настраивать поведение при сборе, что случается редко. увидеть использование .
Вопросы из категории :
- c# Преобразовать десятичную в двойную?
- c# Как рассчитать чей-то возраст в C #?
- c# Как вы сортируете словарь по значению?
- c# В чем разница между int и Integer в Java и C #?
- c# Как создать новый экземпляр объекта из Типа
- c# Datatable против Dataset
- .net Действительно ли опечатанные классы действительно предлагают преимущества?
- .net Setting Objects to Null/Nothing after use in .NET
- .net Почему я не могу иметь абстрактные статические методы в C #?
- generics Почему в C # нельзя хранить объект List <string> в переменной List <object>
- generics Преобразование общего типа из строки
- generics Лучший способ проверить, является ли универсальный тип строкой? (С #)
- generics Есть ли ограничение, которое ограничивает мой общий метод численными типами?
- generics Каковы различия между «универсальными» типами в C ++ и Java?
- generics Приведение списка <int> в список <string> в .NET 2.0