在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()
语句时,这很快就会变得难看。
答案 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
中删除。这意味着完整呼叫将被删除。即使CheckResult
或CalculateSomethingExpensive
有副作用,也将被消除。
有趣的是,这些方法仍保留在编译输出中,只是删除了调用,所以不要使用[Conditional(Debug)]
来隐藏调试期间使用的秘密。