“C#编译器”是否足够聪明,可以删除由于ConditionalAttribute优化而没有副作用的代码

c#

我知道 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)
   {
       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);
}

做这样的事情我是否仍然会更好(在性能方面):

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

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

注意:是的,我确实明白,如果我在循环中运行此代码数百万次,我将创建许多、许多、许多连接对象和可能的 db-connections - 这是描述我的问题的代码,而不是一个片段我的生产代码!:)

回答

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

此外,由于事件订阅本身会导致副作用(通过事件add 方法的自定义实现或类中if(handler!=null){}某处的检查),我认为这种优化并不容易实现。


以上是“C#编译器”是否足够聪明,可以删除由于ConditionalAttribute优化而没有副作用的代码的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>