好吧,这是一个“相当”省力的实现。
工人阶级:
/// <summary>
/// Representation of an unreachable type, exposing a method to represent unreachable code.
/// </summary>
public static class Unreachable {
/// <summary>
/// Representation of unreachable code with return semantics.
/// </summary>
public static dynamic Code() {
throw new NotImplementedException(@"Unreachable code was reached.");
}
}
例子:
public object[] UnreachableCodeTest() {
return Unreachable.Code();
}
反编译:
Offset OpCode Operand
0 ldsfld System.Runtime.CompilerServices.CallSite`1<System.Func`3<System.Runtime.CompilerServices.CallSite,System.Object,System.Object[]>> TestApp.Program/<UnreachableCodeTest>o__SiteContainere6::<>p__Sitee7
5 brtrue.s -> (10) ldsfld System.Runtime.CompilerServices.CallSite`1<System.Func`3<System.Runtime.CompilerServices.CallSite,System.Object,System.Object[]>> TestApp.Program/<UnreachableCodeTest>o__SiteContainere6::<>p__Sitee7
7 ldc.i4.0
8 ldtoken System.Object[]
13 call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
18 ldtoken TestApp.Program
23 call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
28 call System.Runtime.CompilerServices.CallSiteBinder Microsoft.CSharp.RuntimeBinder.Binder::Convert(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags,System.Type,System.Type)
33 call System.Runtime.CompilerServices.CallSite`1<!0> System.Runtime.CompilerServices.CallSite`1<System.Func`3<System.Runtime.CompilerServices.CallSite,System.Object,System.Object[]>>::Create(System.Runtime.CompilerServices.CallSiteBinder)
38 stsfld System.Runtime.CompilerServices.CallSite`1<System.Func`3<System.Runtime.CompilerServices.CallSite,System.Object,System.Object[]>> TestApp.Program/<UnreachableCodeTest>o__SiteContainere6::<>p__Sitee7
43 ldsfld System.Runtime.CompilerServices.CallSite`1<System.Func`3<System.Runtime.CompilerServices.CallSite,System.Object,System.Object[]>> TestApp.Program/<UnreachableCodeTest>o__SiteContainere6::<>p__Sitee7
48 ldfld !0 System.Runtime.CompilerServices.CallSite`1<System.Func`3<System.Runtime.CompilerServices.CallSite,System.Object,System.Object[]>>::Target
53 ldsfld System.Runtime.CompilerServices.CallSite`1<System.Func`3<System.Runtime.CompilerServices.CallSite,System.Object,System.Object[]>> TestApp.Program/<UnreachableCodeTest>o__SiteContainere6::<>p__Sitee7
58 call System.Object TestApp.Unreachable::Code()
63 callvirt !2 System.Func`3<System.Runtime.CompilerServices.CallSite,System.Object,System.Object[]>::Invoke(!0,!1)
68 ret
通过实现带有 Fody 的东西、搜索此调用签名并将其替换为单个原始 ret(如果它允许您)或其他一些简单的可接受的低成本替代方案来进行优化。
(编辑)
当你修改我时,我将被迫解释为什么这是有效和有用的。
大多数情况下,这会进入一个类似于方法末尾的块,该方法具有逻辑上无法到达的路径;
#pragma warning disable 162
// ReSharper disable CSharpWarnings::CS0162
// ReSharper disable HeuristicUnreachableCode
return Unreachable.Code();
// ReSharper restore HeuristicUnreachableCode
// ReSharper restore CSharpWarnings::CS0162
#pragma warning restore 162
如果您以允许访问代码的方式修改本节上方的代码,您的测试将失败。如果你有下面的代码,那你就错了,编译器会让你知道。一旦超出初始成熟度,您将一起删除此代码块。这样做的主要目的是捕捉代码在应该无法访问的情况下。
在其他代码不应到达但编译器无法在逻辑上排除的情况下(例如,案例中的默认语句),您通常会抛出错误。如果要针对这种情况进行优化,则需要这种实现。
select( thisIsAlways123Never0OrGreaterThan3 ) {
default: return Unreachable.Code();
case 1: DoSomething(); break;
case 2: DoSomethingElse(); break;
case 3: return GetSomething();
}
default:
要进行优化,以便使用这种最少编写的代码为路径发出最少的指令,您需要一个名为 Fody 的朋友。
理想的场景是类似于 C++ 开发人员在 GCC 和 LLVM__builtin_unreachable()
或 MSVC__assume(0)
或__declspec(noreturn)
空方法中所期望的结果。