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

发布于 2024-07-19 18:50:28 字数 480 浏览 8 评论 0原文

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

干杯

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.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

心凉怎暖 2024-07-26 18:50:28

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

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

从 LINQ 调用 Enumerable.Cast 然后调用 GetEnumerator() 结果 - 但如果您的类已经实现了 IEnumerable 并且 T 是值类型,则充当无操作,因此 GetEnumerator () 调用会递归并抛出 StackOverflowException。 当 foo 绝对是一个不同对象(不委托)时,使用 return foo.Cast.GetEnumerator(); 是安全的回到这个)但除此之外,您可能最好使用上面的代码。

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. It's safe to use 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.

梦幻之岛 2024-07-26 18:50:28

IEnumerable 已派生自 IEnumerable,因此无需进行任何转换。 您可以简单地转换为它......实际上它是隐式的,不需要转换。

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

对于 LINQ,反之亦然并不困难:

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

IEnumerable<T> already derives from IEnumerable so there's no need to do any conversion. 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:

var fancyEnumerable = list.OfType<GenericObject>();
return fancyEnumerable.GetEnumerator();
瑶笙 2024-07-26 18:50:28

您可以使用 OfTypeCast

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 而不是 IEnumerable,您只需调用 GetEnumerator()

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

You can use OfType<T> and 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()

var enumerator = Digits().OfType<int>().GetEnumerator();
遮了一弯 2024-07-26 18:50:28

我遇到了一些评论中提到的同样的堆栈溢出问题。 就我而言,这是因为 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;
        }
    }
    ...
}

I was running into the same Stack Overflow problem mentioned is some of the comments. 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.

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:

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;
        }
    }
    ...
}
雨落□心尘 2024-07-26 18:50:28

这对我有用。

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

This works for me.

IEnumerator<DataColumn> columnEnumerator = dt.Columns.Cast<DataColumn>().GetEnumerator();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文