使用匿名方法有任何开销吗?

问题描述 投票:7回答:7

我想知道在创建Background worker时是否通过使用匿名方法产生任何开销。

例如:

public void SomeMethod()
{
    BackgroundWorker worker = new BackgroundWorker();
    worker.DoWork += (sender, e) =>
    {
        //large amount of code
    }

    worker.RunWorkerAsync();
}

上面的例子是否比在单独的方法中定义//large amount of code更好或更差?

在线定义后台工作方法是否有任何开销,特别是如果经常调用SomeMethod()

c# anonymous-methods
7个回答
5
投票

从它们创建委托时,处理命名方法和匿名方法的方式略有不同。

匿名方法的委托被缓存,因此检查委托是否已存在于缓存中的开销很小。另一方面,如果您多次运行该方法,它将重用缓存的委托而不是创建新的委托。

命名方法的委托不会被缓存,因此每次都会创建。

除此之外没有区别。匿名方法将在编译时创建,并且像常规方法一样存在于代码中,仅具有只有编译器知道的名称。


2
投票

首先,您可能不应该将大量代码放入匿名方法中。如果为这个方法创建一个单独的方法,甚至更好的方法,它将更具可读性。

对于生成的IL,如果lambda没有关闭任何变量,那么生成的IL代码与将代码放在普通命名方法中的情况相同(除了生成的方法具有不可说的名称)。

另一方面,如果关闭某个变量,编译器会创建一个闭包类来将该变量保存在字段中。并且字段访问比局部变量访问稍微贵一些。

总而言之,如果您关闭某些变量,则开销很小(包括需要进行垃圾回收的更多对象)。在大多数情况下,这并不重要,担心这将是过早的优化。但如果您认为它确实很重要,那么您应该对代码进行分析。


1
投票

每当匿名方法(包括lambdas)关闭变量时,编译器就会创建一个类来为您保存这些变量。每当创建委托时,该类的新实例也是如此。这显然为运行时添加了额外的工作,但在大多数情况下通常可以忽略不计。


0
投票

我前几天测试了这个(通过使用StopWatch类)。据我所知,在直接调用方法之间没有明显的性能差异......

SomeMethod();

......或通过匿名方法......

() => SomeMethod();

0
投票

它主要影响可读性 - 一个地方的大量代码几乎从来都不好;-)

在性能方面,请参阅When is optimization premature?


0
投票

这是反编译员所说的:

[CompilerGenerated]
private static DoWorkEventHandler CS$<>9__CachedAnonymousMethodDelegate1;

[CompilerGenerated]
private static void <SomeMethod1>b__0(object sender, DoWorkEventArgs e)
{
    throw new NotImplementedException();
}

public void SomeMethod1()
{
    BackgroundWorker worker = new BackgroundWorker();
    BackgroundWorker backgroundWorker = worker;
    backgroundWorker.DoWork += (object sender, DoWorkEventArgs e) => throw new NotImplementedException();
    worker.RunWorkerAsync();
}

public void SomeMethod2()
{
    BackgroundWorker worker = new BackgroundWorker();
    worker.DoWork += worker_DoWork;
    worker.RunWorkerAsync();
}

private void worker_DoWork(object sender, DoWorkEventArgs e)
{
    throw new NotImplementedException();
} 

编辑:

查看IL代码,第一次创建/分配方法委派时只需要很小的开销。


© www.soinside.com 2019 - 2024. All rights reserved.