C#编译器如何在发布版本中删除Debug.Assert? [英] How does C# compiler remove Debug.Assert's in release builds?

查看:91
本文介绍了C#编译器如何在发布版本中删除Debug.Assert?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近我经历了一些代码,并考虑是否需要注意 Debug.Assert 语句中的表达式,例如昂贵的操作或具有副作用的语句。但是,编译器似乎完全删除 Assert 语句和内部表达式似乎非常聪明。



例如,以下内容只会在调试版本上打印:

  static void Main(string [] args)
{
Debug.Assert(SideEffect());
}
private static bool SideEffect()
{
Console.WriteLine(Side effect!);
返回true;
}

这将抱怨 o 在发布版本初始化之前被使用:

  static void Main(string [] args)
{
object o;
Debug.Assert(Initialize(out o));
o.ToString();
}
private static bool初始化(out对象o)
{
o = new object();
返回true;
}

甚至可以忍受这样的表达(打印After在这两种情况下):

  static void Main(string [] args)
{
if(false )Debug.Assert(true);
Console.WriteLine(After);
}

我有点惊讶,编译器在这里有多聪明,当 Debug.Assert 被删除时,可以正确检测案例。所以,这让我很好奇。




  • 这个声明究竟是如何被删除的?表达式树必须在语句被移除之前构建才能正确执行上述,如果正确。

  • 是code> System.Diagnostics.Debug 这里的特殊课程,还是可以用类似的处理方法来构建自己的方法?

  • 有没有办法在这里处理预处理器?更好的是,在真实世界的代码中可能遇到的情况可能会有问题吗?


解决方案>

Debug.Assert ConditionalAttribute ;正如文档所述,这个[i]指出编译器应该忽略方法调用或属性,除非定义了指定的条件编译符号。



C#编译器对该属性具有特定的支持,并在发布版本中删除Debug.Assert,所以它不是构建的表达式树的一部分。



如果您右键单击其中一个你的 Debug.Assert 语句,你应该能够去定义。 Visual Studio将显示您从元数据生成的代码,您可以看到应用的 [Conditional(DEBUG)] 属性。因此,当 DEBUG #define '作为构建的一部分时,这个代码才被尊重。


I was recently going through some code and considering whether I need to be careful with the expressions placed inside Debug.Assert statements, such as expensive operations or those with side effects. However, it appears the compiler is pretty smart about completely removing the Assert statement and inner expressions.

For example, the following will only print on debug builds:

static void Main(string[] args)
{
    Debug.Assert(SideEffect());
}
private static bool SideEffect()
{
    Console.WriteLine("Side effect!");
    return true;
}

And this will complain that o is being used before initialization on release builds:

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;
}

It even seems to stand up to expressions such as this (printing "After" in both cases):

static void Main(string[] args)
{
    if (false) Debug.Assert(true);
    Console.WriteLine("After");
}

I was a little suprised with how smart the compiler is here and its ability to correctly detect cases when the Debug.Assert is removed. So, it got me curious..

  • How exactly is the statement removed? The expression tree must be built before the statement is removed in order to properly execute the above if statement correctly.
  • Is the System.Diagnostics.Debug class special here, or is it possible to build your own methods with similar handling?
  • Are there any ways to "trick" the preprocessor here? Even better, are there situations that one might encounter in real-world code where this could be problematic?

解决方案

Debug.Assert is declared with ConditionalAttribute; as the documentation states, this "[i]ndicates to compilers that a method call or attribute should be ignored unless a specified conditional compilation symbol is defined."

The C# compiler has specific support for that attribute and removes the Debug.Assert during release builds, so it is never part of the built expression tree.

If you right-click on one of your Debug.Assert statements, you should be able to go to the definition. Visual Studio will show you "code" generated from the metadata, and there you can see the [Conditional("DEBUG")] attribute applied. So this code is only respected when DEBUG is #define'd as part of your build.

这篇关于C#编译器如何在发布版本中删除Debug.Assert?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆