Недавно я просматривал некоторый код и размышлял, нужно ли мне быть осторожным с выражениями, помещенными в операторы 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;
}
Кажется, что оно даже выдерживает такие выражения (печать «После» в обоих случаях):
static void Main(string[] args)
{
if (false) Debug.Assert(true);
Console.WriteLine("After");
}
Я был немного удивлен тем, насколько умный здесь компилятор и его способность правильно обнаруживать случаи, когда Debug.Assert
удаляется. Так что мне стало любопытно ..
- Как именно удаляется утверждение? Дерево выражений должно быть построено до удаления оператора, чтобы правильно выполнить приведенный выше оператор
if
.
- Является ли класс
System.Diagnostics.Debug
особенным здесь, или возможно создать собственные методы с аналогичной обработкой?
- Есть ли какие-нибудь способы "обмануть" препроцессор здесь? Еще лучше, есть ли ситуации, с которыми можно столкнуться в реальном коде, где это может быть проблематично?