Каков наилучший способ преобразования IEnumerator в общий IEnumerator?
Я пишу пользовательский ConfigurationElementCollection для настраиваемого ConfigurationHandler в С#.NET 3.5, и я хочу показать IEnumerator как общий IEnumerator.
Каким будет лучший способ достичь этого?
В настоящее время я использую код:
public new IEnumerator<GenericObject> GetEnumerator()
{
var list = new List();
var baseEnum = base.GetEnumerator();
while(baseEnum.MoveNext())
{
var obj = baseEnum.Current as GenericObject;
if (obj != null)
list.Add(obj);
}
return list.GetEnumerator();
}
Приветствия
Ответы
Ответ 1
Я не верю в рамки, но вы можете легко написать один:
IEnumerator<T> Cast<T>(IEnumerator iterator)
{
while (iterator.MoveNext())
{
yield return (T) iterator.Current;
}
}
Возникает желание просто вызвать Enumerable.Cast<T>
из LINQ, а затем вызвать GetEnumerator()
в результате - но если ваш класс уже реализует IEnumerable<T>
и T
- это тип значения, который действует как no-op, поэтому вызов GetEnumerator()
рекурсирует и выдает a StackOverflowException
. Безопасно использовать return foo.Cast<T>.GetEnumerator();
, когда foo
определенно является другим объектом (который не передает его обратно), но в противном случае вам, вероятно, лучше всего использовать код выше.
Ответ 2
IEnumerable<T>
уже происходит от IEnumerable
, поэтому нет необходимости делать какое-либо преобразование. Вы можете просто наложить на него... ну на самом деле это неявное отсутствие необходимости.
IEnumerable<T> enumerable = GetGenericFromSomewhere();
IEnumerable sadOldEnumerable = enumerable;
return sadOldEnumerable.GetEnumerator();
Переход с другой стороны в LINQ не намного труднее:
var fancyEnumerable = list.OfType<GenericObject>();
return fancyEnumerable.GetEnumerator();
Ответ 3
Вы можете использовать OfType<T>
и Cast<T>
.
public static IEnumerable Digits()
{
return new[]{1, 15, 68, 1235, 12390, 1239};
}
var enumerable = Digits().OfType<int>();
foreach (var item in enumerable)
// var is here an int. Without the OfType<int(), it would be an object
Console.WriteLine(i);
Чтобы получить IEnumerator<T>
вместо IEnumerable<T>
, вы можете просто позвонить GetEnumerator()
var enumerator = Digits().OfType<int>().GetEnumerator();
Ответ 4
Это работает для меня.
IEnumerator<DataColumn> columnEnumerator = dt.Columns.Cast<DataColumn>().GetEnumerator();
Ответ 5
Я столкнулся с той же проблемой, о которой упоминалось в некоторых комментариях. В моем случае это было связано с тем, что вызов GetEnumerator должен был быть в base.GetEnumerator, иначе вы зацикливаетесь в своем собственном переопределении GetEnumerator.
Это код, который был "Бросок". Использование оператора foreach вызывает ту же функцию GetEnumerator, которую я пытаюсь перегрузить:
public new IEnumerator<T> GetEnumerator()
{
foreach (T type in this)
{
yield return type;
}
}
Я закончил с упрощенной версией исходного сообщения, так как вам не нужно использовать держатель List.
public class ElementCollection<T> : ConfigurationElementCollection, IList<T>
...
public new IEnumerator<T> GetEnumerator()
{
var baseEnum = base.GetEnumerator();
while (baseEnum.MoveNext())
{
yield return baseEnum.Current as T;
}
}
...
}