条件编译是否优化了生成输入参数的方法?
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
中删除。这意味着删除了完整的调用。即使 CheckResult
或 CalculateSomethingExpensive
有副作用,也会被移除。
有趣的是,这些方法仍然存在于编译后的输出中,只是删除了调用,所以不要使用 [Conditional(Debug)]
来隐藏调试期间使用的秘密。
在 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
中删除。这意味着删除了完整的调用。即使 CheckResult
或 CalculateSomethingExpensive
有副作用,也会被移除。
有趣的是,这些方法仍然存在于编译后的输出中,只是删除了调用,所以不要使用 [Conditional(Debug)]
来隐藏调试期间使用的秘密。