C# 将带out参数的块体方法转换为表达式体方法会导致out参数为null

C# 将带out参数的块体方法转换为表达式体方法会导致out参数为null,c#,out-parameters,expression-body,C#,Out Parameters,Expression Body,我有以下通过单元测试的方法: public static bool TryGetInstance<T>(out T config) where T : class { return Instance.TryGetInstance(out config); } 公共静态bool TryGetInstance(out T config),其中T:class { return Instance.TryGetInstance(out-config);

我有以下通过单元测试的方法:

    public static bool TryGetInstance<T>(out T config) where T : class
    {
        return Instance.TryGetInstance(out config);
    }
公共静态bool TryGetInstance(out T config),其中T:class
{
return Instance.TryGetInstance(out-config);
}
当我将其转换为表达式体语法时,单元测试失败了吗

    public static bool TryGetInstance<T>(out T config) where T : class => 
        Instance.TryGetInstance(out config);
publicstaticbooltrygetstance(out T config),其中T:class=>
TryGetInstance(out-config);
失败的测试断言该方法返回true,并且为config返回的实例不为null。我假设这些编译成完全相同的IL


为什么会发生这种情况?

它们在语义上是相同的

IL是相同的:

    .method public hidebysig static 
        bool TryGetInstance1<class T> (
            [out] !!T& config
        ) cil managed 
    {
        // Method begins at RVA 0x2050
        // Code size 12 (0xc)
        .maxstack 8

        IL_0000: call class Foo P::get_Instance()
        IL_0005: ldarg.0
        IL_0006: callvirt instance bool Foo::TryGetInstance<!!T>(!!0&)
        IL_000b: ret
    } // end of method P::TryGetInstance1

    .method public hidebysig static 
        bool TryGetInstance2<class T> (
            [out] !!T& config
        ) cil managed 
    {
        // Method begins at RVA 0x205d
        // Code size 12 (0xc)
        .maxstack 8

        IL_0000: call class Foo P::get_Instance()
        IL_0005: ldarg.0
        IL_0006: callvirt instance bool Foo::TryGetInstance<!!T>(!!0&)
        IL_000b: ret
    } // end of method P::TryGetInstance2
.method公共隐藏静态
bool TryGetInstance1(
[输出]!!T&config
)cil管理
{
//方法从RVA 0x2050开始
//代码大小12(0xc)
.maxstack 8
IL_0000:调用类Foo P::get_Instance()
IL_0005:ldarg.0
IL_0006:callvirt实例bool Foo::TryGetInstance(!!0&)
IL_000b:ret
}//方法P::TryGetInstance1的结尾
.方法公共隐藏静态
bool TryGetInstance2(
[输出]!!T&config
)cil管理
{
//方法从RVA 0x205d开始
//代码大小12(0xc)
.maxstack 8
IL_0000:调用类Foo P::get_Instance()
IL_0005:ldarg.0
IL_0006:callvirt实例bool Foo::TryGetInstance(!!0&)
IL_000b:ret
}//方法P::TryGetInstance2的结尾
所以:两件事之一:

  • 您已经破坏了编译器或JIT
  • 错误不在你认为的地方
  • 第二种选择更为常见。尝试还原仅此方法更改,然后查看问题是否消失


    如果是这样的话:微软的人会对一个复制感兴趣。

    他们在语义上是相同的

    IL是相同的:

        .method public hidebysig static 
            bool TryGetInstance1<class T> (
                [out] !!T& config
            ) cil managed 
        {
            // Method begins at RVA 0x2050
            // Code size 12 (0xc)
            .maxstack 8
    
            IL_0000: call class Foo P::get_Instance()
            IL_0005: ldarg.0
            IL_0006: callvirt instance bool Foo::TryGetInstance<!!T>(!!0&)
            IL_000b: ret
        } // end of method P::TryGetInstance1
    
        .method public hidebysig static 
            bool TryGetInstance2<class T> (
                [out] !!T& config
            ) cil managed 
        {
            // Method begins at RVA 0x205d
            // Code size 12 (0xc)
            .maxstack 8
    
            IL_0000: call class Foo P::get_Instance()
            IL_0005: ldarg.0
            IL_0006: callvirt instance bool Foo::TryGetInstance<!!T>(!!0&)
            IL_000b: ret
        } // end of method P::TryGetInstance2
    
    .method公共隐藏静态
    bool TryGetInstance1(
    [输出]!!T&config
    )cil管理
    {
    //方法从RVA 0x2050开始
    //代码大小12(0xc)
    .maxstack 8
    IL_0000:调用类Foo P::get_Instance()
    IL_0005:ldarg.0
    IL_0006:callvirt实例bool Foo::TryGetInstance(!!0&)
    IL_000b:ret
    }//方法P::TryGetInstance1的结尾
    .方法公共隐藏静态
    bool TryGetInstance2(
    [输出]!!T&config
    )cil管理
    {
    //方法从RVA 0x205d开始
    //代码大小12(0xc)
    .maxstack 8
    IL_0000:调用类Foo P::get_Instance()
    IL_0005:ldarg.0
    IL_0006:callvirt实例bool Foo::TryGetInstance(!!0&)
    IL_000b:ret
    }//方法P::TryGetInstance2的结尾
    
    所以:两件事之一:

  • 您已经破坏了编译器或JIT
  • 错误不在你认为的地方
  • 第二种选择更为常见。尝试还原仅此方法更改,然后查看问题是否消失


    如果是这样的话:微软的人会对一个复制感兴趣。

    他们在语义上是相同的,并且在我的机器上编译到同一个IL(启用了优化)。您必须深入挖掘(框架版本、编译器版本、在上下文中使用),以了解您的计算机上是否存在这种情况。它们在语义上相同,并且在我的计算机上编译为相同的IL(启用优化)。您必须深入挖掘(框架版本、编译器版本、在上下文中使用)以确定您的计算机上是否存在这种情况。在两种语法样式之间切换会导致单元测试中断。看来问题可能是由于我的单元测试无意中共享了状态。当我评出除一项测试外的所有测试时,它始终通过。我认为测试的执行顺序在重构之间一定发生了变化。我修改了我的分解方法,现在所有测试都通过了,不管我使用什么语法样式。@mark_h和“option 2”wins Other time:)测试的并发性和顺序是导致失败的常见原因-大多数测试框架都有防止某些测试并行运行的机制—在两种语法样式之间的翻转始终会导致单元测试中断。看来问题可能是由于我的单元测试无意中共享了状态。当我评出除一项测试外的所有测试时,它始终通过。我认为测试的执行顺序在重构之间一定发生了变化。我修改了我的分解方法,现在所有测试都通过了,不管我使用哪种语法样式。@mark_h和“option 2”再次获胜:)测试的并发性和顺序是失败的常见原因-大多数测试框架都有防止某些测试并行运行的机制