将IEnumerator转换为通用IEnumerator的最佳方法是什么?

时间:2009-05-06 06:54:12

标签: c# enumeration ienumerator

我正在为C#.NET 3.5中的自定义ConfigurationHandler编写自定义ConfigurationElementCollection,并且我希望将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 个答案:

答案 0 :(得分:50)

我不相信框架中有任何内容,但您可以轻松地编写一个:

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

从LINQ调用Enumerable.Cast<T>然后在结果上调用GetEnumerator()很诱人 - 但如果您的类已经实现了IEnumerable<T>并且T是值类型,那么充当无操作,因此GetEnumerator()调用会递归并抛出StackOverflowException。当return foo.Cast<T>.GetEnumerator();肯定是不同的对象(不会委托给它)时,使用foo是安全的,否则,你可能最好使用代码上方。

答案 1 :(得分:3)

IEnumerable<T>已经来自IEnumerable,因此无需进行任何转化。你可以简单地投射到它......实际上它是暗示没有必要的演员。

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

对于LINQ来说,反过来并不困难:

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

答案 2 :(得分:1)

我遇到了同样的Stack Overflow问题,提到了一些评论。在我的情况下,这是因为GetEnumerator调用需要到base.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;
        }
    }
    ...
}

答案 3 :(得分: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();

答案 4 :(得分:0)

这适合我。

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