条件编译是否优化了生成输入参数的方法?

Does conditional compilation optimise away methods that generate input arguments?

在 C# 中,我们可以使用 #if / #endif 语句或 Conditional 属性执行条件编译。例如,以下代码将仅为调试版本打印一些内容:

public static void Main(string[] args)
{
    CheckResult();
}

[Conditional("DEBUG")]
private static void CheckResult() 
{ 
    System.Console.WriteLine("everything is fine");
}

但是,如果这个 CheckResult() 方法接受参数,并且我们像这样使用它,会发生什么?

public static void Main(string[] args)
{
    CheckResult(CalculateSomethingExpensive() == 100);
}

private static int CalculateSomethingExpensive()
{
    result = //some sort of expensive operation here
    return result;
}

[Conditional("DEBUG")]
private static void CheckResult(bool resultIsOK) 
{ 
    System.Console.WriteLine(resultIsOK ? "OK" : "not OK");
}

在这种情况下,什么编译器规则决定昂贵的方法是被执行还是被优化掉?例如,如果它不改变任何对象的状态,它是否保证被删除?

我知道可以通过显式使用 #if 来消除不确定性,但是当一个人拥有包含数百个 Debug.Assert() 语句的大型代码库时,这很快就会变得难看。

所以,稍微修改一下,这是编译的(在 Release 下):

class Program
{
    public static void Main(string[] args)
    {
        CheckResult(CalculateSomethingExpensive() == 100);
    }

    private static int CalculateSomethingExpensive()
    {
        var result = new Random().Next(100);//some sort of expensive operation here
        return result;
    }

    [Conditional("DEBUG")]
    private static void CheckResult(bool resultIsOK)
    {
        System.Console.WriteLine(resultIsOK ? "OK" : "not OK");
    }
}

这与您的示例几乎相同,只是为了编译进行了修改。编译它然后 运行 通过反编译器,结果是:

internal class Program
{
    public Program()
    {
    }

    private static int CalculateSomethingExpensive()
    {
        return (new Random()).Next(100);
    }

    [Conditional("DEBUG")]
    private static void CheckResult(bool resultIsOK)
    {
        Console.WriteLine((resultIsOK ? "OK" : "not OK"));
    }

    public static void Main(string[] args)
    {
    }
}

您可以看到唯一的区别是 CheckResult 调用从 Main 中删除。这意味着删除了完整的调用。即使 CheckResultCalculateSomethingExpensive 有副作用,也会被移除。

有趣的是,这些方法仍然存在于编译后的输出中,只是删除了调用,所以不要使用 [Conditional(Debug)] 来隐藏调试期间使用的秘密。