c# - 2013 和 2015 调试编译之间的匿名方法静态性不同

标签 c#

我希望有人可以识别导致以下程序行为发生变化的语言功能(或错误)。它是从一个更大的场景中复制的,如果提供给 Orchard::Go 的委托(delegate)不是静态的,该场景旨在记录一条消息。

using System;

namespace Sample
{
    public static class Program
    {
        public static void Main()
        {
            new Apple();
        }
    }

    public sealed class Apple
    {
        public Apple()
        {
            Orchard.Go(() => { });
        }
    }

    internal static class Orchard
    {
        public static void Go(Action action)
        {
            Console.WriteLine(action.Method.IsStatic);
        }
    }
}

场景是:

  • 如果我编译并运行使用 Visual Studio 2013 生成的调试 版本,输出为True
  • 如果我编译并运行使用 Visual Studio 2015 生成的调试 版本,输出为False
  • 在这两种情况下,目标 .NET Framework 都是 4.5。
  • 如果我编译并运行使用 Visual Studio 2015 生成的release 版本,输出为 True(因此与 Visual Studio 2013 一致)。
  • Visual Studio 2015 是 RC 版本(如果重要的话)。

我可以从 ildasm 看到 2013 生成的代码...


    ___[MOD] C:\Sample.exe
       |      M A N I F E S T
       |___[NSP] Sample
       |   |___[CLS] Sample.Apple
       |   |   |     .class public auto ansi sealed beforefieldinit 
       |   |   |___[STF] CS$9__CachedAnonymousMethodDelegate1 : private static class [mscorlib]System.Action
       |   |   |___[MET] .ctor : void()
       |   |   |     b__0 : void()
       |   |
       |   |___[CLS] Sample.Orchard
       |   |   |     .class private abstract auto ansi sealed beforefieldinit 
       |   |   |___[STM] Go : void(class [mscorlib]System.Action)
       |   |
       |   |___[CLS] Sample.Program
       |   |   |     .class public abstract auto ansi sealed beforefieldinit 
       |   |   |___[STM] Main : void()
       |   |
       |

...与 2015 年生成的代码明显不同...


    ___[MOD] C:\Sample.exe
       |      M A N I F E S T
       |___[NSP] Sample
       |   |___[CLS] Sample.Apple
       |   |   |     .class public auto ansi sealed beforefieldinit 
       |   |   |___[CLS] c
       |   |   |   |     .class nested private auto ansi serializable sealed beforefieldinit 
       |   |   |   |     .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )  ...
       |   |   |   |___[STF] 9 : public static initonly class Sample.Apple/'c'
       |   |   |   |___[STF] 9__0_0 : public static class [mscorlib]System.Action
       |   |   |   |___[STM] .cctor : void()
       |   |   |   |___[MET] .ctor : void()
       |   |   |   |     b__0_0 : void()
       |   |   |
       |   |   |___[MET] .ctor : void()
       |   |
       |   |___[CLS] Sample.Orchard
       |   |   |     .class private abstract auto ansi sealed beforefieldinit 
       |   |   |___[STM] Go : void(class [mscorlib]System.Action)
       |   |
       |   |___[CLS] Sample.Program
       |   |   |     .class public abstract auto ansi sealed beforefieldinit 
       |   |   |___[STM] Main : void()
       |   |
       |

...但我对 IL 和编译器更改的了解不足以确定这是新功能还是意外错误。我可以根据要求生成完整的 IL 转储,但是任何人都可以根据我提供的信息告诉我这里发生了什么以及它是否是故意的?为什么匿名方法在 2013 年被认为是静态的,但在 2015 年被认为是非静态的?

最佳答案

我将此问题记录为 Microsoft Connect 票证 here并提供了对 C# 规范的引用,该规范确认您不能依赖匿名方法的封闭类型的任何特定实现。具体来说,

6.5.1/2 "The invocation list of a delegate produced from an anonymous function contains a single entry. The exact target object and target method of the delegate are unspecified. In particular, it is unspecified whether the target object of the delegate is null, the this value of the enclosing function member, or some other object."

Microsoft Connect 票证也链接到类似的问题 here如果有人感兴趣。因此,就我而言,具体而言,编译器似乎“按预期工作”,而我的问题的解决方案是“不那样做”。

关于c# - 2013 和 2015 调试编译之间的匿名方法静态性不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30906720/

相关文章:

c# - 对象类型具有 ToString()、GetHashCode()、GetType 等方法的原因是什么

c# - 如何在 C# 中重定向

c# - 我的服务器程序接收到的字节不完整。为什么?我正在使用 C# .net 套接字

javascript - 如何将 json 数据从 C# Controller 传递到 Angular js?

c# - 如何重复失败的测试,以便它仅在 x 次重复后失败?

c# - 从 C# 中的 SQL 查询返回位值

c# - 在 DevExpress PivotGridControl 中使用 DisplayNameAttribute

c# - 使用 Moq 对 LINQ to SQL CRUD 操作进行单元测试

c# - C# 中固定深度的树状数据的最佳数据结构是什么?

javascript - Kendo 日期选择器 - 将错误的日期格式传递给 Controller