“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){}某处的检查),我认为这种优化并不容易实现。
THE END
二维码