简体   繁体   English

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

[英]What is the best way to convert an IEnumerator to a generic IEnumerator?

I am writing a custom ConfigurationElementCollection for a custom ConfigurationHandler in C#.NET 3.5 and I am wanting to expose the IEnumerator as a generic IEnumerator. 我正在为C#.NET 3.5中的自定义ConfigurationHandler编写自定义ConfigurationElementCollection,并且我希望将IEnumerator公开为通用IEnumerator。

What would be the best way to achieve this? 实现这一目标的最佳方法是什么?

I am currently using the code: 我目前正在使用该代码:

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();
}

Cheers 干杯

I don't believe there's anything in the framework, but you could easily write one: 我不相信框架中有任何内容,但您可以轻松地编写一个:

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

It's tempting to just call Enumerable.Cast<T> from LINQ and then call GetEnumerator() on the result - but if your class already implements IEnumerable<T> and T is a value type, that acts as a no-op, so the GetEnumerator() call recurses and throws a StackOverflowException . 从LINQ调用Enumerable.Cast<T>然后在结果上调用GetEnumerator()很诱人 - 但是如果你的类已经实现了IEnumerable<T>T是一个值类型,那么它就像一个no-op,所以GetEnumerator()调用recurses并抛出StackOverflowException It's safe to use return foo.Cast<T>.GetEnumerator(); 使用return foo.Cast<T>.GetEnumerator(); when foo is definitely a different object (which doesn't delegate back to this one) but otherwise, you're probably best off using the code above. foo绝对是一个不同的对象(它不会委托给这个对象),但除此之外,你可能最好使用上面的代码。

IEnumerable<T> already derives from IEnumerable so there's no need to do any conversion. IEnumerable<T>已经从IEnumerable派生,所以不需要进行任何转换。 You can simply cast to it...well actually it's implicit no cast necessary. 你可以简单地投射它......实际上它隐含没有必要的演员。

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

Going the other way round isn't much more difficult with LINQ: 对于LINQ来说,反过来说并不困难:

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

I was running into the same Stack Overflow problem mentioned is some of the comments. 我遇到的同样是Stack Overflow问题,提到了一些评论。 In my case it was due to the fact that the GetEnumerator call needed to be to the base.GetEnumerator otherwise you loop within your own GetEnumerator redefinition. 在我的情况下,这是因为GetEnumerator调用需要到base.GetEnumerator,否则你在自己的GetEnumerator重定义中循环。

This is the code that was Throwing the Stack Overflow. 这是抛出堆栈溢出的代码。 The use of the foreach statement call the same GetEnumerator function I'm trying to overload: 使用foreach语句调用我正在尝试重载的相同GetEnumerator函数:

public new IEnumerator<T> GetEnumerator()
{
    foreach (T type in this)
    {
        yield return type;
    }
}

I've ended up with a simplified version of the original post as you don't need to use a List holder. 我最终得到了原始帖子的简化版本,因为您不需要使用列表持有者。

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;
        }
    }
    ...
}

这适合我。

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

You can use OfType<T> and Cast<T> . 您可以使用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);

To get an IEnumerator<T> instead of an IEnumerable<T> you can just make a call to GetEnumerator() 要获取IEnumerator<T>而不是IEnumerable<T>您只需调用GetEnumerator()

var enumerator = Digits().OfType<int>().GetEnumerator();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM