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