允许迭代,而不会产生任何垃圾 [英] Allowing iteration without generating any garbage

查看:177
本文介绍了允许迭代,而不会产生任何垃圾的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在实现IEnumerable接口的对象池下面的代码

I have the following code in an object pool that implements the IEnumerable interface.

public IEnumerable<T> ActiveNodes
{
    get
    {
        for (int i = 0; i < _pool.Count; i++)
        {
            if (_pool[i].AvailableInPool)
            {
                yield return _pool[i];
            }
        }
    }
}



由于据我(据这个问题)知道,这将产生的垃圾为对象的IEnumerable需要被收集。在_pool元素
都永远不会被收集,为池的目的是保持引用所有这些,以防止垃圾创建

As far as I know (according to this question), this will generate garbage as the IEnumerable object will need to be collected. None of the elements in _pool will ever be collected, as the purpose of the pool is to keep references to all of them to prevent garbage creation.

灿有人提出一个办法,让迭代超过_pool这样就不会产生垃圾?

Can anyone suggest a way to allow iteration over _pool so that no garbage is generated?

当过池迭代,都在池中的项目有 AvailableInPool ==真应迭代。顺序并不重要。

When iterating over pool, all of the items in pool that have AvailableInPool == true should be iterated over. Order doesn't matter.

推荐答案

迭代的项目将在任何正常的设计总是导致创建一个新的枚举对象。创建和处理的对象是非常快的,所以只有在非常特殊的情况下(分别为低延迟是最上面的优先级)的垃圾收集可能(我说'可以')是一个问题。

Iterating items will in any 'normal' design always result in the creation of a new enumerable object. Creating and disposing objects is very fast, so only in very special scenarios (were low latency is the top most priority) garbage collections could (I say 'could') be a problem.

垃圾没有一个设计可以通过返回的结构不的实施的IEnumerable 。 C#编译器仍然可以遍历这样的对象,因为的foreach 语句使用鸭打字。但同样,它是不太可能这会帮助你。

A design without garbage is possible by returning structures that don't implement IEnumerable. The C# compiler can still iterate such objects, because the foreach statement uses duck typing. But again, it is unlikely this is going to help you.

更新

我相信在提高应用程序的性能,比造成这种低水平的挂羊头卖狗肉更好的方法,但它是你的电话。这是一个结构枚举和struct枚举。当您返回可枚举,C#编译器可以在的foreach是:

I believe there are better ways in increasing performance of your application, than resulting in this low level trickery, but it's your call. Here is a struct enumerable and struct enumerator. When you return the enumerable, the C# compiler can foreach over it:

public struct StructEnumerable<T>
{
    private readonly List<T> pool;

    public StructEnumerable(List<T> pool)
    {
        this.pool = pool;
    }

    public StructEnumerator<T> GetEnumerator()
    {
        return new StructEnumerator<T>(this.pool);
    }
}

下面是 StructEnumerator

public struct StructEnumerator<T>
{
    private readonly List<T> pool;
    private int index;

    public StructEnumerator(List<T> pool)
    {
        this.pool = pool;
        this.index = 0;
    }

    public T Current
    {
        get
        {
            if (this.pool == null || this.index == 0)
                throw new InvalidOperationException();

            return this.pool[this.index - 1];
        }
    }

    public bool MoveNext()
    {
        this.index++;
        return this.pool != null && this.pool.Count >= this.index;
    }

    public void Reset()
    {
        this.index = 0;
    }
}

您可以简单地返回 StructEnumerable< T> 如下:

You can simply return the StructEnumerable<T> as follows:

public StructEnumerable<T> Items
{
    get { return new StructEnumerable<T>(this.pool); }
}

和C#可以正常的foreach遍历这个:

And C# can iterate over this with a normal foreach:

foreach (var item in pool.Items)
{
    Console.WriteLine(item);
}

请注意,你不能LINQ在项目上。您需要为IEnumerable接口,并涉及拳击和垃圾收集。

Note that you can't LINQ over the item. You need the IEnumerable interface for that, and that involves boxing and garbage collection.

祝你好运。

这篇关于允许迭代,而不会产生任何垃圾的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆