避免重复分配没有变量/成员的Action对象

时间:2012-02-02 16:25:55

标签: c# allocation object-lifetime

通常我需要在非常频繁运行的代码中最小化对象分配 当然我可以使用像对象池这样的常规技术,但有时我只想要一些本地包含的东西 为了实现这一目标,我想出了以下内容:

public static class Reusable<T> where T : new()
{
    private static T _Internal;
    private static Action<T> _ResetAction;

    static Reusable()
    {
        _Internal = Activator.CreateInstance<T>();
    }

    public static void SetResetAction(Action<T> resetAction)
    {
        _ResetAction = resetAction;
    }

    public static T Get()
    {
#if DEBUG
        if (_ResetAction == null)
        {
            throw new InvalidOperationException("You must set the reset action first");
        }
#endif

        _ResetAction(_Internal);

        return _Internal;
    }
}

目前,用法是:

// In initialisation function somewhere
Reuseable<List<int>>.SetResetAction((l) => l.Clear());

....

// In loop
var list = Reuseable<List<int>>.Get();
// Do stuff with list

我想要改进的是,整个事物不包含在一个地方(.SetResetAction与实际使用的地方分开)。

我想将代码改为以下内容:

// In loop

var list = Reuseable<List<int>>.Get((l) => l.Clear());
// Do stuff with list

这个问题是我得到一个对象分配(它创建一个Action<T>)每个循环。

是否可以在没有任何对象分配的情况下获得我的用法?

显然我可以创建一个内置ReuseableList<T>的{​​{1}},但我想允许其他情况可能会有所不同。

1 个答案:

答案 0 :(得分:4)

确定在每次迭代时创建一个新的Action<T>吗?我怀疑它实际上没有,因为它没有捕获任何变量。我怀疑如果你看一下C#编译器生成的IL,它会缓存委托。

当然,那是特定于实现的......

编辑:(在我有时间写作之前我刚刚离开......)

正如埃里克在评论中指出的那样,依靠这一点并不是一个好主意。它不能保证,即使你不改变编译器也很容易意外破坏它。

即使这样的设计看起来令人担忧(线程安全?)但是如果你必须这样做,我可能会把它从静态类变成一个采用重置方法的“普通”类(可能是实例)在构造函数中。这是一种更灵活,可读和可测试的方法IMO。