如何创建 IEnumerable哪些多重枚举是不可能的?

发布于 2024-12-18 20:05:15 字数 594 浏览 2 评论 0原文

当我枚举 IEnumerable 两次时,Resharper 抱怨 可能多次枚举 IEnumerable。我知道,在某些数据库查询的情况下,当您枚举两次时,您会得到异常。

我想在测试中重现这种行为。所以,我基本上希望抛出以下函数(因为多个枚举):

    private void MultipleEnumerations(IEnumerable<string> enumerable)
    {
        MessageBox.Show(enumerable.Count().ToString());
        MessageBox.Show(enumerable.Count().ToString());
    }

我应该传递什么给它?所有列表、集合等都可以使用多个枚举。 即使这种 IEnumerable 也不例外:

    private IEnumerable<string> GetIEnumerable()
    {
        yield return "a";
        yield return "b";
    }

谢谢。

When I enumerate over an IEnumerable twice Resharper complains about Possible multiple enumerations of IEnumerable. I know, in some case of DB-queries when you enumerate twice you get an exception.

I want to reproduce that behavior in tests. So, I basically want the following function to throw (because of multiple enumerations):

    private void MultipleEnumerations(IEnumerable<string> enumerable)
    {
        MessageBox.Show(enumerable.Count().ToString());
        MessageBox.Show(enumerable.Count().ToString());
    }

What should I pass to it? All the Lists, Collections etc. are ok with multiple enumerations.
Even this kind of IEnumerable doesn't give an exception:

    private IEnumerable<string> GetIEnumerable()
    {
        yield return "a";
        yield return "b";
    }

Thanks.

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

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

发布评论

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

评论(3

挖鼻大婶 2024-12-25 20:05:15

您可能只想要一个自定义类:

public class OneShotEnumerable<T> : IEnumerable<T>
{
    private readonly IEnumerable<T> _source;
    private bool _shouldThrow = false;

    public OneShotEnumerable(IEnumerable<T> source)
    {
        this._source = source;
    }

    public IEnumerator<T> GetEnumerator()
    {
        if (_shouldThrow) throw new InvalidOperationException();
        _shouldThrow = true;

        return _source.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

You probably just want a custom class:

public class OneShotEnumerable<T> : IEnumerable<T>
{
    private readonly IEnumerable<T> _source;
    private bool _shouldThrow = false;

    public OneShotEnumerable(IEnumerable<T> source)
    {
        this._source = source;
    }

    public IEnumerator<T> GetEnumerator()
    {
        if (_shouldThrow) throw new InvalidOperationException();
        _shouldThrow = true;

        return _source.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}
活泼老夫 2024-12-25 20:05:15

创建您自己的类来实现 IEnumerable,并在调用 GetEnumerator() 两次时引发异常(使用布尔实例字段)。

或者,创建一个使用标志字段的迭代器,以确保它不能被调用两次(枚举迭代器两次将执行整个方法两次)。

Create your own class that implements IEnumerable<T> and throw an exception if GetEnumerator() is called twice (use a boolean instance field).

Alternatively, create an iterator that uses a flag field to ensure that it cannot be called twice (enumerating an iterator twice will execute the entire method twice).

你的心境我的脸 2024-12-25 20:05:15

我从 John Gietzen 的答案中复制的自定义类(经过一些更正)可以有效地与扩展方法结合起来,以创建一种非常简单的方法来执行此操作。

public class OneShotEnumerable<T> : IEnumerable<T>
{
    private readonly IEnumerable<T> source;
    private bool shouldThrow = false;

    public OneShotEnumerable(IEnumerable<T> source)
    {
        this.source = source;
    }

    public IEnumerator<T> GetEnumerator()
    {
        if (shouldThrow) 
            throw new InvalidOperationException("This enumerable has already been enumerated.");

        shouldThrow = true;

        return this.source.GetEnumerator();
    }
}

public static clas OneShotEnumerableExtension
{
    public static IEnumerable<T> SingleUse<T>(this IEnumerable<T> source)
    {
#if (DEBUG)
        return new OneShotEnumerableExtension(source);
#else
        return source;
#endif
    }
}

然后你可以通过简单地把一些东西传递给你以前的方法

MultipleEnumerations(MyEnumerable.SingleUse());

The custom class, which I've copied from John Gietzen's answer (with a couple of corrections), could usefully be combined with an extension method to create a really simple way to do this.

public class OneShotEnumerable<T> : IEnumerable<T>
{
    private readonly IEnumerable<T> source;
    private bool shouldThrow = false;

    public OneShotEnumerable(IEnumerable<T> source)
    {
        this.source = source;
    }

    public IEnumerator<T> GetEnumerator()
    {
        if (shouldThrow) 
            throw new InvalidOperationException("This enumerable has already been enumerated.");

        shouldThrow = true;

        return this.source.GetEnumerator();
    }
}

public static clas OneShotEnumerableExtension
{
    public static IEnumerable<T> SingleUse<T>(this IEnumerable<T> source)
    {
#if (DEBUG)
        return new OneShotEnumerableExtension(source);
#else
        return source;
#endif
    }
}

Then you can pass something to your previous method by simply doing

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