Sco*_*ock 9 c# compiler-optimization
我有一些代码在Release版本和Debug版本之间表现不同.它在Debug中正常运行,但在Release中不正常.
我有一个函数返回一个ReadOnlyCollection<MyCustomClass>.一节是这样的:
var result = new List<MyCustomClass>();
...
var list1 = this.returnEmptyList();
var list2 = this.returnListWithOneItem();
if (list1.Count == 0 && list2.Count == 0)
{
functionOutVariable = string.Empty;
return result.AsReadOnly();
}
Run Code Online (Sandbox Code Playgroud)
出于故障排除的目的,我简化了代码并以通用方式命名变量,方法returnEmptyList和returnListWithOneItem方法如下所示:
private List<string> returnEmptyList()
{
return new List<string>();
}
private List<string> returnListWithOneItem()
{
return new List<string> {"something"};
}
Run Code Online (Sandbox Code Playgroud)
显然它永远不应该进入if块,因为它list2.Count应该始终为1,但是当我在Release版本中执行它时,它会:
因此,显然有一些优化正在进行,因为您可以看到它list1是不可访问的,并且当单步执行它时执行第416行然后立即跳转到第421行.我应该声明我的解决方案中的所有程序集都使用.NET Framework 4.6.2,并且我正在运行Visual Studio 2017版本15.3.5.
当我改变构建调试和执行这一点,执行管线416,417,和上线418它显示list1.Count为0和list2.Count1,并正确并不能进入if块.
我正在尝试制作一个测试项目来重现这一点,但我不能.我正在寻找任何方法来深究这一点.我不仅仅想要一个让它消失的修复 - 我需要了解我做错了什么.
好吧,我很确定这是我的函数其余部分中的一个微妙错误的结果,它允许编译器优化if块并提前返回.我可以在这个测试项目中重现调试器的行为,在这种情况下它完全有意义:
class Program
{
static void Main(string[] args)
{
var test = new MyClass();
test.DoTest(out var result);
Console.WriteLine(result);
Console.ReadKey();
}
}
class MyClass
{
public ReadOnlyCollection<MyCustomClass> DoTest(out string functionOutVariable)
{
var result = new List<MyCustomClass>();
var list1 = this.returnEmptyList();
var list2 = this.returnListWithOneItem();
if (list1.Count == 0 && list2.Count == 0)
{
functionOutVariable = string.Empty;
return result.AsReadOnly();
}
functionOutVariable = string.Empty;
return result.AsReadOnly();
}
private List<string> returnEmptyList()
{
return new List<string>();
}
private List<string> returnListWithOneItem()
{
return new List<string> { "something" };
}
}
class MyCustomClass
{
}
Run Code Online (Sandbox Code Playgroud)
当我在一个发布版本与调试器中执行,这似乎进入if块,但实际上它只是优化了if块完全和调试器混淆的显示它执行里面的线if,而不是跳过它块:
编辑:我已经确认函数后面有一个错误导致了我的问题,并且在查看Release构建代码时调试器的行为只是由于编译器优化而导致我混淆.
要清楚,我的问题是不正确的:该函数实际上在Release和Debug版本中都给出了相同的结果,但我错了.那是因为我遵循了这个(有缺陷的)序列:
if不正确地进入块.if块. 我假设(错误地)这是我的问题的根源.这让我在上面看到了疯狂的追逐.很抱歉浪费你的时间,但我当然发现这项运动信息丰富.也许其他人将来会从我的错误中吸取教训.:)
| 归档时间: |
|
| 查看次数: |
147 次 |
| 最近记录: |