为啥 Roslyn 在尝试重写此 lambda 时会崩溃? (Visual Studio 2015 更新 1)

Posted

技术标签:

【中文标题】为啥 Roslyn 在尝试重写此 lambda 时会崩溃? (Visual Studio 2015 更新 1)【英文标题】:Why does Roslyn crash when trying to rewrite this lambda? (Visual Studio 2015 update 1)为什么 Roslyn 在尝试重写此 lambda 时会崩溃? (Visual Studio 2015 更新 1) 【发布时间】:2016-03-09 05:03:00 【问题描述】:

我刚刚升级到 VS2015.1,在尝试编译我的一个项目时遇到了编译器崩溃。如果您将以下 repo 代码放在控制台应用程序中(并添加对 moq.dll 的引用),第 12 行中的代码会使我的编译器崩溃。这似乎发生在 Roslyn lamdba 重写调用期间。

using System.Collections.Generic;
using System.Linq;
using Moq;

namespace RoslynError

  class Program
  
    static void Main(string[] args)
    
      var mockRepo = new MockRepository(MockBehavior.Strict);
      var obj = mockRepo.OneOf<DTO>(x => x.Value == (OptionEnum?)null);
    
  

  class DTO 
  
    public DTO(OptionEnum? enumVal)
    
      Value = enumVal;
        

    public OptionEnum? Value;
  

  enum OptionEnum
  
    NotSpecified    
  

有人知道为什么会发生崩溃吗?

【问题讨论】:

对起订量的引用几乎不相关。我认为重要的是 lambda 箭头将被转换为表达式树(Expression&lt;Func&lt;DTO, bool&gt;&gt; 类型),而不是简单的委托实例(Func&lt;DTO, bool&gt; 类型)。 【参考方案1】:

下面更简单的例子也重现了这个问题,这与重写表达式树中的类型转换节点有关:

using System;
using System.Linq.Expressions;

namespace Bug461

  class Program
  
    enum Test  

    static void Main()
    
      Expression<Func<Test?, bool>> x = t => t == (Test?)null;
    
  

编辑:我稍微编辑了代码以避免出现警告。

编辑 2:该错误是由https://github.com/dotnet/roslyn/commit/5c602fc6 引起的,其中降级的枚举操作数(即 null 文字)没有关联类型。

编辑 3:我提出了一个带有建议修复的拉取请求:https://github.com/dotnet/roslyn/pull/7227

【讨论】:

在tryroslyn.azurewebsites.net 编译。将不可为空的tnull 进行比较是一个有效的警告。在问题的代码中,== 运算符的两边都已经可以为空(没有换行)。 是的,但是当我在 Visual Studio 中本地编译它时它仍然崩溃,尽管只安装了 VS 2015 更新 1。 @SuneFoldager:因为您发出了无效代码:D 请参阅 PR 中的测试失败。 PS:你还应该在你的 PR 中添加测试。 @leppie:是的,我更新了 PR。诀窍是在我们有显式可空类型转换的情况下不应用 github.com/dotnet/roslyn/commit/5c602fc6 中的缩减。不幸的是,我们似乎无法完全区分这些情况:( 我的 PR 已合并。

以上是关于为啥 Roslyn 在尝试重写此 lambda 时会崩溃? (Visual Studio 2015 更新 1)的主要内容,如果未能解决你的问题,请参考以下文章

使用 Roslyn 生成 getter 和 setter lambda

如何将此lamda函数重写为常规函数

为啥以下代码编译失败(C++ lambda问题)

在 python 3 中使用 map 和 lambdas,为啥这段代码不会更新 sql 表

JAVA中重写equals方法为啥要重写hashcode方法说明

为啥我的 lambda 函数在尝试访问 S3 存储桶时会被拒绝访问?