31

我正在为 C#.NET 3.5 中的自定义 ConfigurationHandler 编写自定义 ConfigurationElementCollection,并且我想将 IEnumerator 公开为通用 IEnumerator。

实现这一目标的最佳方法是什么?

我目前正在使用代码:

公共新 IEnumerator<GenericObject> GetEnumerator()
{
  var list = new List();
  var baseEnum = base.GetEnumerator();
  而(baseEnum.MoveNext())
  {
    var obj = baseEnum.Current 作为 GenericObject;
    如果 (obj != null)
      list.Add(obj);
  }
  返回列表.GetEnumerator();
}

干杯

4

5 回答 5

56

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

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

Enumerable.Cast<T>只从 LINQ 调用然后调用结果是很诱人GetEnumerator()的——但是如果你的类已经实现IEnumerable<T>并且T是一个值类型,那么它就充当一个无操作,所以GetEnumerator()调用递归并抛出一个StackOverflowException. 使用return foo.Cast<T>.GetEnumerator();whenfoo绝对是一个不同的对象(它不会委托回这个对象)是安全的,但否则,您最好使用上面的代码。

于 2009-05-06T07:18:45.867 回答
3

IEnumerable<T>已经派生自,IEnumerable因此无需进行任何转换。您可以简单地对其进行强制转换......实际上它是隐含的,不需要强制转换。

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

使用 LINQ 反过来并不困难:

var fancyEnumerable = list.OfType<GenericObject>();
return fancyEnumerable.GetEnumerator();
于 2009-05-06T06:57:16.027 回答
1

您可以使用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();
于 2009-05-06T13:18:43.787 回答
1

我遇到了一些评论中提到的相同的堆栈溢出问题。在我的情况下,这是因为 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;
        }
    }
    ...
}
于 2015-06-10T23:17:05.937 回答
0

这对我有用。

IEnumerator<DataColumn> columnEnumerator = dt.Columns.Cast<DataColumn>().GetEnumerator();
于 2014-12-16T17:37:12.607 回答