"the C# compiler" 是否足够聪明,可以删除由于 ConditionalAttribute 优化而没有副作用的代码

Is "the C# compiler" clever enough to remove code that has no side effect due to ConditionalAttribute optimization

我知道 Debug.WriteLine 方法应用了 ConditionalAttribute。这意味着当发布构建完成时(或任何未定义 DEBUG 符号的构建)- 此代码将从构建中排除。

这非常适合我想做的事情(在调试我的代码时显示额外的调试信息 - 但在生产中有非常优化的代码)。我的系统每分钟处理数百万条记录并且没有用户交互,所以速度为王,即使以其他资源为代价。

所以,如果我在这样的代码上进行发布构建:

using (var connection = new SqlConnection(_connectionString))
{
   connection.InfoMessage += delegate (object sender, SqlInfoMessageEventArgs e)
   {
       Debug.WriteLine(e.Message);
   };
   return connection.Execute("procName", commandType: CMD.StoredProcedure);
}

我应该这样结束:

using (var connection = new SqlConnection(_connectionString))
{
   connection.InfoMessage += delegate (object sender, SqlInfoMessageEventArgs e)
   {
   };
   return connection.Execute("procName", commandType: CMD.StoredProcedure);
}

所以,最后的问题是:“编译器”通常是否足够聪明,可以看到下面的代码什么都不做并将其删除 - 或者它是否仍会生成一个空的 class + 方法并分别调用它时间代码 运行s? (我相信委托会编译为包含该方法的“存根”-class - 因此这确实存在一些开销)。

   connection.InfoMessage += delegate (object sender, SqlInfoMessageEventArgs e)
   {
   };

做这样的事情(在性能方面)我还会更好吗:

using (var connection = new SqlConnection(_connectionString))
{
#if DEBUG 
   connection.InfoMessage += delegate (object sender, SqlInfoMessageEventArgs e)
   {
   };
#endif
   return connection.Execute("procName", commandType: CMD.StoredProcedure);
}

据我所知 - 看起来 C# 编译器应该删除单个 Debug.Writeline() 调用,然后 JIT 编译器可能会删除空方法。这个假设准确吗?

注意: 是的,我明白如果我 运行 将此代码循环数百万次,我将创建很多很多连接对象和可能的数据库连接——这是描述我的问题的代码,而不是我的生产代码片段! :)

正如我们在compilation results中看到的,编译器不会消除事件订阅。它将添加空主体的事件处理程序。

此外,由于事件订阅本身会导致副作用(通过事件 add method 的自定义实现或在 class), 我不认为这样的优化会很容易实现。