Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/259.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# “C编译器”是否足够聪明,可以删除由于条件属性优化而没有副作用的代码_C#_.net_Roslyn - Fatal编程技术网

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

C# “C编译器”是否足够聪明,可以删除由于条件属性优化而没有副作用的代码,c#,.net,roslyn,C#,.net,Roslyn,我知道Debug.WriteLine方法应用了ConditionalAttribute。这意味着,当发布构建完成或任何未定义调试符号的构建完成时,此代码将从构建中排除 这非常适合我在调试代码时显示额外的调试信息,但在生产中有非常优化的代码。我的系统每分钟处理数百万条记录,并且没有用户交互,因此速度是第一位的,即使以牺牲其他资源为代价 因此,如果我在这样的代码上进行发布构建: using (var connection = new SqlConnection(_connectionString))

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

这非常适合我在调试代码时显示额外的调试信息,但在生产中有非常优化的代码。我的系统每分钟处理数百万条记录,并且没有用户交互,因此速度是第一位的,即使以牺牲其他资源为代价

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

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

使用var connection=newsqlconnection\u connectionString { connection.InfoMessage+=委托对象发送方,SqlInfoMessageEventArgs e { }; return connection.ExecuteprocName,commandType:CMD.StoredProcedure; } 所以,最后一个问题是:编译器是否足够聪明,能够看到下面的代码什么都不做,并且也会删除它?或者它是否仍然会生成一个空的class+方法,并在每次代码运行时调用它?我相信委托会编译成一个包含方法的存根类——因此这会带来一些实际的开销

connection.InfoMessage+=委托对象发送方,SqlInfoMessageEventArgs e { }; 做这样的事,我的表现会更好吗

using (var connection = new SqlConnection(_connectionString))
{
   connection.InfoMessage += delegate (object sender, SqlInfoMessageEventArgs e)
   {
       Debug.WriteLine(e.Message);
   };
   return connection.Execute("procName", commandType: CMD.StoredProcedure);
}
使用var connection=newsqlconnection\u connectionString { 如果调试 connection.InfoMessage+=委托对象发送方,SqlInfoMessageEventArgs e { }; 恩迪夫 return connection.ExecuteprocName,commandType:CMD.StoredProcedure; } 正如我所知道的,看起来C编译器应该删除单个Debug.Writeline调用,然后JIT编译器可能会删除空方法。这个假设准确吗

注意:是的,我知道如果我在一个循环中运行此代码数百万次,我将创建很多很多连接对象,可能还有db连接-这是描述我的问题的代码,而不是我的生产代码片段!:

如中所示,编译器不会消除事件订阅。它将添加主体为空的事件处理程序

此外,由于事件订阅本身可能会通过事件的add的自定义实现或使用ifhandler之类的检查导致副作用=null{}在类中的某个地方,我认为这样的优化不容易实现。

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


此外,由于事件订阅本身可能会通过事件的add的自定义实现或使用ifhandler之类的检查导致副作用=空{}在类中的某个地方,我认为这样的优化不容易实现。

回答这个问题的最佳方法是比较生成的IL。但就我个人而言,我更喜欢明确说明什么会在prod中结束,什么会留在debug中,所以if才是解决问题的方法。我将创建很多很多很多连接对象-创建连接实例与创建其他对象不同,但它不会创建很多数据库连接,数据库连接将由连接池提供,连接池将重用已创建的连接。@Franz Gleichmann谢谢。我大体上同意直言不讳,除非有人在另一个方向上有令人信服的论点,否则很可能会以直言不讳而告终。我对if语句的唯一反对意见是,它们会让代码看起来很难看::@Fabio。我大体上同意你的说法-除了a我不认为对象创建的成本很小-对象创建可能非常昂贵,b我希望问题集中在编译器问题上,而不是支持代码。回想起来,也许我应该用一个非db的例子来写这篇文章。c只有当您对我的连接字符串的内容做出一些全面的假设时,您的观察才是正确的。我可以在我的连接字符串中禁用连接池。当你第二次执行InfoMessage+=游戏结束时,没有什么能完全优化它。无论如何,用benchmarkdotneb向自己证明这一点。回答这个问题的最佳方法是比较生成的IL。但就我个人而言,我更喜欢明确说明什么会在prod中结束,什么会留在debug中,所以if才是解决问题的方法。我将创建很多很多很多连接对象-创建连接实例与创建其他对象不同,但它不会创建很多数据库连接,数据库连接将由连接池提供,连接池将重用已创建的连接。@Franz Gleichmann谢谢。我大体上同意直言不讳,除非有人在另一个方向上有令人信服的论点,否则很可能会以直言不讳而告终。我对if语句的唯一反对意见是它们倾向于使代码lo
好丑::@Fabio。我大体上同意你的说法-除了a我不认为对象创建的成本很小-对象创建可能非常昂贵,b我希望问题集中在编译器问题上,而不是支持代码。回想起来,也许我应该用一个非db的例子来写这篇文章。c只有当您对我的连接字符串的内容做出一些全面的假设时,您的观察才是正确的。我可以在我的连接字符串中禁用连接池。当你第二次执行InfoMessage+=游戏结束时,没有什么能完全优化它。无论如何,用BenchmarkDotNetThanks@Serg向自己证明这一点。这完全有道理。我甚至没有考虑Add方法可能产生的副作用…谢谢@ Serg。这完全有道理。我甚至没有考虑Add方法可能会带来的副作用。