2009-05-06 4 views
28

Я пишу пользовательский ConfigurationElementCollection для настраиваемого ConfigurationHandler в C# .NET 3.5, и я хочу показать IEnumerator как общий IEnumerator.Каков наилучший способ преобразования 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(); 
} 

Приветствия

ответ

45

Я не верю, что есть что-то в рамках, но вы могли бы легко написать один:

IEnumerator<T> Cast<T>(IEnumerator iterator) 
{ 
    while (iterator.MoveNext()) 
    { 
     yield return (T) iterator.Current; 
    } 
} 

Забавно просто позвонить Enumerable.Cast<T> из LINQ, а затем набрать GetEnumerator(), но если ваш класс уже реализует IEnumerable<T> и T - тип значения, который действует как нет-op, поэтому вызов GetEnumerator() выполняет повторную проверку и выдает StackOverflowException. Безопасно использовать return foo.Cast<T>.GetEnumerator();, когда foo определенно является другим объектом (который не передает его обратно), но в противном случае вам, вероятно, лучше всего использовать приведенный выше код.

+7

Не можете ли вы просто вернуть Enumerator из броска? return this.Cast () .GetEnumerator(); – flq

+0

Фрэнк: Ты абсолютно прав :) –

+0

Вот оно спасибо. Спасибо всем за ваши ответы. – zonkflut

3

IEnumerable<T> уже черпает из IEnumerable так что нет необходимости делать какие-либо преобразования. Вы можете просто наброситься на него ... ну на самом деле это неявное отсутствие необходимости.

IEnumerable<T> enumerable = GetGenericFromSomewhere(); 
IEnumerable sadOldEnumerable = enumerable; 
return sadOldEnumerable.GetEnumerator(); 

Going наоборот не намного сложнее с LINQ:

var fancyEnumerable = list.OfType<GenericObject>(); 
return fancyEnumerable.GetEnumerator(); 
+0

Моей плохо пропустил общую часть моего определения метода – zonkflut

+2

Вы путаете IEnumerable и IEnumerator. IEnumerable происходит от IEnumerable и IEnumerator происходит от IEnumerator.Не имеет смысла говорить «IEnumerable theEnumerator», потому что перечисляемый не является перечислителем. –

+0

Кастинг не работает, поскольку в родительском объекте коллекция хранится в ArrayList. – zonkflut

0

Вы можете использовать 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(); 
0

Это работает для меня.

IEnumerator<DataColumn> columnEnumerator = dt.Columns.Cast<DataColumn>().GetEnumerator(); 
0

Я столкнулся с той же проблемой переполнения стека, о которой упоминалось в некоторых комментариях. В моем случае это было связано с тем, что вызов GetEnumerator должен был быть в base.GetEnumerator, иначе вы зацикливаетесь в своем собственном переопределении GetEnumerator.

Это код, который выбрасывает переполнение стека. Использование заявления Еогеасп называют ту же функцию 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; 
     } 
    } 
    ... 
} 

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

  • Нет связанных вопросов^_^