我有一个相当深奥的案例,我需要一些永远不会执行但仍需要成为编译输出的一部分的代码。虽然我可以提出自己的想法,但我在问社区:什么是最简单、最快的 C# 表达式,它总是评估为 false 并且不会生成编译器警告并在最终构建输出中保留封闭的代码块?
更新:由于要求解释问题背后的基本原理:Monotouch 链接器执行静态代码分析,以便从最终构建中删除所有未引用的符号,以减小生成的二进制文件的大小。这对仅通过反射访问的属性提出了问题。
我有一个相当深奥的案例,我需要一些永远不会执行但仍需要成为编译输出的一部分的代码。虽然我可以提出自己的想法,但我在问社区:什么是最简单、最快的 C# 表达式,它总是评估为 false 并且不会生成编译器警告并在最终构建输出中保留封闭的代码块?
更新:由于要求解释问题背后的基本原理:Monotouch 链接器执行静态代码分析,以便从最终构建中删除所有未引用的符号,以减小生成的二进制文件的大小。这对仅通过反射访问的属性提出了问题。
我会选择简单的...
public static bool False() {
return false;
}
public static void Foo() {
if (False()) {
...
}
}
如果您也需要说服 JIT(内联),请添加[MethodImpl(MethodImplOptions.NoInlining)]
到False()
[第二次编辑]
在我看来,@Guillaume 在对 OP 的评论中提出了正确的答案,他建议 OP 应该使用自定义链接来确保所讨论的属性不会被优化:http ://docs.xamarin.com /guides/ios/advanced_topics/linker#3.custom-linking
如果@Guillaume 将其写为答案,我将删除此编辑,以便他能够正确获得荣誉。
原答案:
怎么样:
if ("".Length > 0)
我在反射器中检查了此代码以获取发布版本(VS2012,.Net 4.5)
void Run()
{
if ("".Length > 0)
{
Console.WriteLine();
}
}
它产生这个IL:
.method private hidebysig instance void Run() cil managed
{
.maxstack 8
L_0000: ldstr ""
L_0005: callvirt instance int32 [mscorlib]System.String::get_Length()
L_000a: ldc.i4.0
L_000b: ble L_0015
L_0010: call void [mscorlib]System.Console::WriteLine()
L_0015: ret
}
编辑:由于似乎有一些关于这是否可行的争论,让我提供更多证据。
目标是确保生成的代码可以访问属性。
鉴于此 C# 代码:
using System;
using System.Diagnostics;
namespace ConsoleApplication1
{
class Program
{
static void Main()
{
new Program().Run();
}
void Run()
{
if ("".Length > 0)
{
Test t = new Test();
Trace.WriteLine(t.Property); // Make sure we use the property.
}
}
}
internal class Test
{
public int Property { get; set; }
}
}
Run()
为发布构建的方法生成的 IL 代码是:
.method private hidebysig instance void Run() cil managed
{
.maxstack 5
.locals init (
[0] class ConsoleApplication1.Test t)
L_0000: ldstr ""
L_0005: callvirt instance int32 [mscorlib]System.String::get_Length()
L_000a: ldc.i4.0
L_000b: ble L_0026
L_0010: newobj instance void ConsoleApplication1.Test::.ctor()
L_0015: stloc.0
L_0016: ldloc.0
L_0017: callvirt instance int32 ConsoleApplication1.Test::get_Property()
L_001c: box int32
L_0021: call void [System]System.Diagnostics.Trace::WriteLine(object)
L_0026: ret
}
所以该属性肯定在输出代码中被引用;因此,这满足了要求。
我认为当您知道它不为空时测试对象引用 == null 将是最快的。
更新。看看其他一些答案,我的猜测是,与您从您的逻辑中知道的东西相比,任何在独立上明显是错误的东西都更有可能被优化掉(如果不是今天,那么可能在将来)程序必须是假的。就低级操作码而言,测试 != 0 是我所知道的最快的操作之一。
也许像这样归档
volatile bool val = false;
我只是想在这里发挥创意(不建议以前提出的任何建议),也许:
if (new object().GetType() == typeof(string))
我认为这不会被优化掉,但我并不是真的在一个可以测试的地方。
if(false)
{
}
...将是我的猜测:)
//Try using `if(1 == 2) {...}`, is that what you want?
编辑:我认为编译器不应该检测到以下一个:
if(this.GetType().ToString().Equals(string.Empty)
{
......
}