gpt4 book ai didi

c# - 为什么闭包对于使用声明的 C# 8.0 中的变量不同?

转载 作者:太空狗 更新时间:2023-10-29 19:40:17 26 4
gpt4 key购买 nike

我注意到 C# 8.0 编译器为捕获的 IDisposable 变量构建闭包类的方式有所不同,这些变量是使用 C# 8.0 using 声明声明的,与使用经典 using 语句声明的变量相反.

考虑这个简单的类:

public class DisposableClass : IDisposable
{
public void Dispose() { }
}

还有这个示例代码:

public void Test()
{
using var disposable1 = new DisposableClass();
using var disposable2 = new DisposableClass();

Action action = () => Console.Write($"{disposable1}{disposable2}");
}

编译器生成这段代码:

[CompilerGenerated]
private sealed class <>c__DisplayClass0_0
{
public DisposableClass disposable1;

public DisposableClass disposable2;

internal void <Test>b__0()
{
Console.Write(string.Format("{0}{1}", disposable1, disposable2));
}
}

public void Test()
{
<>c__DisplayClass0_0 <>c__DisplayClass0_ = new <>c__DisplayClass0_0();
<>c__DisplayClass0_.disposable1 = new DisposableClass();
try
{
<>c__DisplayClass0_.disposable2 = new DisposableClass();
try
{
Action action = new Action(<>c__DisplayClass0_.<Test>b__0);
}
finally
{
if (<>c__DisplayClass0_.disposable2 != null)
{
((IDisposable)<>c__DisplayClass0_.disposable2).Dispose();
}
}
}
finally
{
if (<>c__DisplayClass0_.disposable1 != null)
{
((IDisposable)<>c__DisplayClass0_.disposable1).Dispose();
}
}
}

这看起来完全没问题。但后来我注意到,如果我用 using 语句声明这两个变量,则生成的闭包类会大不相同。这是示例代码:

public void Test()
{
using (var disposable1 = new DisposableClass())
using (var disposable2 = new DisposableClass())
{
Action action = () => Console.Write($"{disposable1}{disposable2}");
}
}

这就是我得到的:

[CompilerGenerated]
private sealed class <>c__DisplayClass0_0
{
public DisposableClass disposable1;
}

[CompilerGenerated]
private sealed class <>c__DisplayClass0_1
{
public DisposableClass disposable2;

public <>c__DisplayClass0_0 CS$<>8__locals1;

internal void <Test>b__0()
{
Console.Write(string.Format("{0}{1}", CS$<>8__locals1.disposable1, disposable2));
}
}

为什么会这样?其余代码看起来完全相同,而且我认为 using 声明应该与 using 声明完全相同,后者被视为阻止它在其中声明的当前 block 。

更不用说为使用声明生成闭包类的方式看起来更清晰,最重要的是,通过反射更容易探索。

如果有人知道为什么会这样,我希望得到一些见解。

谢谢!

最佳答案

编译器正在为每个“作用域”生成一个[CompilerGenerated] class...在第一个例子中,有一个作用域,整个测试() 方法。在第二个示例中(您没有给出),有两个范围,两个 using

第二个例子的代码大概是:

public void Test()
{
using (var disposable1 = new DisposableClass())
{
using (var disposable2 = new DisposableClass())
{
Action action = () => Console.Write($"{disposable1}{disposable2}");
}
}
}

正如 juharr 所指出的,这两个代码块产生相同的代码:

using (DisposableClass disposable1 = new DisposableClass(), disposable2 = new DisposableClass())
{
Action action = () => Console.Write($"{disposable1}{disposable2}");
}

using var disposable1 = new DisposableClass();
using var disposable2 = new DisposableClass();

Action action = () => Console.Write($"{disposable1}{disposable2}");

关于c# - 为什么闭包对于使用声明的 C# 8.0 中的变量不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57593184/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com