让我们考虑一下这个非常简单的异步方法:

static async Task myMethodAsync() 
{
    await Task.Delay(500);
}

当我用VS2013(前Roslyn编译器)编译时,生成的状态机是一个 struct .

private struct <myMethodAsync>d__0 : IAsyncStateMachine
{  
    ...
    void IAsyncStateMachine.MoveNext()
    {
        ...
    }
}

当我用VS2015(Roslyn)编译它时,生成的代码如下:

private sealed class <myMethodAsync>d__1 : IAsyncStateMachine
{
    ...
    void IAsyncStateMachine.MoveNext()
    {
        ...
    }
}

正如你所见,Roslyn生成了一个类(而不是 struct ).如果我没记错的话,在旧编译器(我猜是CTP2012)中,async/await支持的第一个实现也生成了类,然后出于性能原因,它被更改为struct.(在某些情况下,可以完全避免装箱和堆分配…(参见this)

有人知道为什么罗斯林的情况又变了吗?(我对此没有任何问题,我知道这个更改是透明的,不会改变任何代码的行为,我只是好奇)

Edit:

来自@Damien_The_unsiver(以及源代码:)的答案解释了一切.所描述的Roslyn行为仅适用于调试构建(由于注释中提到的CLR限制,这是必需的).在发行版中,它还会生成一个 struct (具有所有这些优点).因此,这似乎是一个非常聪明的解决方案,可以支持编辑和继续,并在生产中获得更好的性能.有趣的东西,感谢所有参与的人!

推荐答案

我对这一点没有任何先见之明,但由于Roslyn现在是开源的,我们可以通过代码寻找解释.

在这里,在line 60 of the AsyncRewriter,我们发现:

// The CLR doesn't support adding fields to structs, so in order to enable EnC in an async method we need to generate a class.
var typeKind = compilationState.Compilation.Options.EnableEditAndContinue ? TypeKind.Class : TypeKind.Struct;

因此,虽然使用structs有一定的吸引力,但允许Edit and Continue种方法在async种方法中工作的巨大胜利显然被选为更好的 Select .

.net相关问答推荐

从窗体中移除另一个控件中引用的控件时获取设计时通知

如何将 signalR 添加到不同项目中的后台服务?

.NET Core 中的微服务

更改列表中的值

如何找到windows服务exe路径

mstest.exe 在哪里?

来自奥尔森时区的 .NET TimeZoneInfo

如何对无法加载的 VSTO 插件进行故障排除?

将 C# 编译为本机?

所有数组在 C# 中都实现了哪些接口?

监听依赖属性的变化

将字典值转换为数组

将日期时间转换为时间跨度

ConcurrentDictionary TryRemove 何时返回 false

清除文件内容

IronPython 与 Python .NET

System.Array.CopyTo() 和 System.Array.Clone() 之间的区别

如何为我的 C# 应用程序创建产品密钥?

程序员应该使用 SSIS,如果是,为什么?

多个列表与 IEnumerable.Intersect() 的交集