Каков наилучший способ преобразования IEnumerator в общий IEnumerator?
Я пишу пользовательский ConfigurationElementCollection для пользовательского ConfigurationHandler в C#.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(); }
Ура
5 ответов
Я не верю, что есть что-то в рамках, но вы могли бы легко написать один:
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()
звонок повторяется и бросает!--6-->. Это безопасно использовать return foo.Cast<T>.GetEnumerator();
, когда foo
определенно разные объект (который не делегирует обратно на этот), но в противном случае вам, вероятно, лучше всего использовать приведенный выше код.
IEnumerable<T>
уже вытекает из IEnumerable
Так что нет необходимости выполнять какие-либо преобразования. Вы можете просто бросить его...ну на самом деле это неявный нет необходимости.
IEnumerable<T> enumerable = GetGenericFromSomewhere();
IEnumerable sadOldEnumerable = enumerable;
return sadOldEnumerable.GetEnumerator();
идти в другую сторону не намного сложнее с LINQ:
var fancyEnumerable = list.OfType<GenericObject>();
return fancyEnumerable.GetEnumerator();
можно использовать 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();
это работает для меня.
IEnumerator<DataColumn> columnEnumerator = dt.Columns.Cast<DataColumn>().GetEnumerator();
я столкнулся с той же проблемой переполнения стека, о которой упоминалось в некоторых комментариях. В моем случае это было связано с тем, что вызов GetEnumerator должен был быть на базе.GetEnumerator в противном случае вы выполняете цикл в своем собственном переопределении GetEnumerator.
это код, который бросал переполнение стека. Использование оператора foreach вызывает ту же функцию GetEnumerator, которую я пытаюсь перегрузить:
public new IEnumerator<T> GetEnumerator()
{
foreach (T type in this)
{
yield return type;
}
}
Я закончил с упрощенной версией оригинальный пост, поскольку вам не нужно использовать держатель списка.
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;
}
}
...
}