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

时间:2018-10-14 03:43:19

标签: c# optimization compiler-optimization conditional-compilation

在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()语句时,这很快就会变得难看。

1 个答案:

答案 0 :(得分:2)

因此,只需稍作修改,即可编译(在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)]来隐藏调试期间使用的秘密。