最近我在查看一些代码,考虑是否需要注意放置在Debug.Assert
语句中的表达式,例如昂贵的操作或具有副作用的操作。不过,事实证明编译器非常聪明,能够完全删除Assert
语句和内部表达式。
例如,以下代码仅会在调试构建时打印:
static void Main(string[] args)
{
Debug.Assert(SideEffect());
}
private static bool SideEffect()
{
Console.WriteLine("Side effect!");
return true;
}
在发布版本中,这会提示使用了未初始化的变量 o
:
static void Main(string[] args)
{
object o;
Debug.Assert(Initialize(out o));
o.ToString();
}
private static bool Initialize(out object o)
{
o = new object();
return true;
}
它甚至能够处理类似于这样的表达式(在两种情况下都打印 "After"):
static void Main(string[] args)
{
if (false) Debug.Assert(true);
Console.WriteLine("After");
}
编译器的聪明之处让我有些惊讶,它可以正确检测出Debug.Assert
被移除的情况。这让我很好奇...
- 这个语句是如何被移除的?在正确执行上述
if
语句之前,必须先构建表达式树并删除该语句。 System.Diagnostics.Debug
类在这里是否特殊?还是可能创建具有类似处理方式的自定义方法?- 有没有什么方法可以在这里“欺骗”预处理器?更好的是,是否会在实际代码中遇到可能会产生问题的情况?