0

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

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>内置的,Action但我想允许其他情况下操作可能会有所不同。

4

1 回答 1

4

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

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

编辑:(我还没来得及写就离开了……)

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

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

于 2012-02-02T16:28:14.627 回答