5

我有一个相当深奥的案例,我需要一些永远不会执行但仍需要成为编译输出的一部分的代码。虽然我可以提出自己的想法,但我在问社区:什么是最简单、最快的 C# 表达式,它总是评估为 false 并且不会生成编译器警告并在最终构建输出中保留封闭的代码块?

更新:由于要求解释问题背后的基本原理:Monotouch 链接器执行静态代码分析,以便从最终构建中删除所有未引用的符号,以减小生成的二进制文件的大小。这对仅通过反射访问的属性提出了问题。

4

7 回答 7

6

我会选择简单的...

public static bool False() {
    return false;
}
public static void Foo() {
    if (False()) {
       ...
    }
}

如果您也需要说服 JIT(内联),请添加[MethodImpl(MethodImplOptions.NoInlining)]False()

于 2013-05-13T08:02:49.790 回答
5

[第二次编辑]

在我看来,@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 
}

所以该属性肯定在输出代码中被引用;因此,这满足了要求。

于 2013-05-13T07:50:32.983 回答
2

我认为当您知道它不为空时测试对象引用 == null 将是最快的。

更新。看看其他一些答案,我的猜测是,与您从您的逻辑中知道的东西相比,任何在独立上明显是错误的东西都更有可能被优化掉(如果不是今天,那么可能在将来)程序必须是假的。就低级操作码而言,测试 != 0 是我所知道的最快的操作之一。

于 2013-05-13T07:49:52.400 回答
2

也许像这样归档

 volatile bool val = false;
于 2013-05-13T08:09:46.640 回答
1

我只是想在这里发挥创意(不建议以前提出的任何建议),也许:

if (new object().GetType() == typeof(string))

我认为这不会被优化掉,但我并不是真的在一个可以测试的地方。

于 2013-05-13T08:02:40.587 回答
0
if(false)
{
}

...将是我的猜测:)

于 2013-05-13T07:50:16.170 回答
0
//Try using `if(1 == 2) {...}`, is that what you want? 

编辑:我认为编译器不应该检测到以下一个:

if(this.GetType().ToString().Equals(string.Empty)
{
    ......
}
于 2013-05-13T07:50:18.803 回答