【问题标题】:Will an empty delegate eat up memory?一个空的代表会吃掉内存吗?
【发布时间】:2009-03-31 20:54:23
【问题描述】:
public sealed class FtpManager
{
    public event EventHandler LoggingIn = delegate { };
    private void OnLoggingIn(object sender, EventArgs e)
    {
        var handler = LoggingIn;
        handler(sender, e);
    }
// ...
}

在上面的代码中,我使用空委托初始化了LoggingIn 事件处理程序。

这会影响以任何方式使用的内存空间吗?尤其是当有成百上千的事件以这种方式声明时?

【问题讨论】:

  • 不要忘记涉及的额外方法调用。您将调用事件处理程序和您通过匿名委托分配的空方法。我还没有进行任何测试,但你至少应该意识到这一点......

标签: .net events memory-management delegates


【解决方案1】:

刮掉上一个答案(保留在下面以供后代使用)。这取决于编译器的实现,但在当前的 MS C# 3.0 编译器下,这实际上只创建了一个实例,每个实例都可以重用该实例。它之所以能够做到这一点,是因为委托是不可变的,并且该委托不需要来自实例的任何信息。

我不知道 C# 2.0 是否是这种情况。您可以反编译您的代码并查看 IL 是否实际使用缓存字段。使用下面的答案是一种保证您只会创建一个实例的安全方法。

原答案:

是的,它创建了一个委托的实例。这将需要一些记忆。你可以减少它:

public static class EventHandlers
{
    public static readonly EventHandler Empty = delegate {};
}

public sealed class FtpManager
{
    public event EventHandler LoggingIn = EventHandlers.Empty;
}

那时只有一个实例,您可以从任何地方引用它。缺点是其他类可以使用相同的处理程序取消订阅。如果您相信代码库的其余部分不会这样做,那么从内存的角度来看,这可能是最好的选择。

【讨论】:

  • 哇,我认为我的应用程序因高内存使用而疯狂运行的部分原因可能是因为我一直在用空委托声明事件......;再次感谢,乔恩
  • @Sung:我已经完全改变了我的答案。将返回并编辑以放置以前的版本!
  • @Sung:好的,现在它已经完成了很多。您应该能够通过反编译您的应用程序来检查这是否是您的问题。 Reflector 对此很有用,但您需要查看 IL 以确定实际发生的情况。
【解决方案2】:

这样做的替代方法是在每次您想提高它时检查 LoggingIn 是否为空。这可能比调用空委托更占用内存。

【讨论】:

  • 您是否运行了任何测试来支持这一点,或者只是一个假设?
  • 没有。我只是指出了一个限制因素。如果你想要测试,你可以像其他人一样轻松地编写它们。
猜你喜欢
  • 1970-01-01
  • 2021-03-24
  • 1970-01-01
  • 2011-02-28
  • 1970-01-01
  • 2011-05-04
  • 1970-01-01
  • 2020-05-20
  • 1970-01-01
相关资源
最近更新 更多