【发布时间】:2011-10-27 09:31:53
【问题描述】:
我在我的 C# 代码中使用了一个非常简单的三元表达式:
helperClass.SomeData = helperClass.HasData ? GetSomeData() : GetSomeOtherData();
在这两种情况下,表达式的每个路径上的函数都返回一个非空对象,但是如果我在调试器中查看结果,它是空的,直到我在代码中引用它,例如使用断言:
Debug.Assert(helperClass.SomeData != null);
只有在调试模式下使用“x64”或“任何 CPU”平台设置时才会出现这种情况。在“x86”模式下没问题。
在假设我在编译器或调试器中发现错误之前,我会非常谨慎,但我找不到任何其他解释此行为的原因。
这是一个完整的类来做repro,只需在x64模式下在调试器中调用SomeClass.SomeAction()并逐步查看它:
public class SomeClass {
public bool HasData;
public object SomeData;
private SomeClass() {
HasData = false;
}
public static void SomeAction() {
var helperClass = new SomeClass();
// Exhibits weird debugger behavior of having helperClass.SomeData = null after this line:
helperClass.SomeData = helperClass.HasData ? GetSomeData() : GetSomeOtherData();
// Note that trying helperClass.SomeData.ToString() returns a debugger error saying SomeData is null
// But this code is just fine
//if(helperClass.HasData) {
// helperClass.SomeData = GetSomeData();
//}
//else {
// helperClass.SomeData = GetSomeOtherData();
//}
// In both cases though, after this line things are fine:
Debug.Assert(helperClass.SomeData != null);
}
private static object GetSomeData() {
return new object();
}
private static object GetSomeOtherData() {
return new object();
}
}
是我遗漏了什么还是 x64 调试器中的错误?我正在使用调试模式,因此不应该存在任何优化。
【问题讨论】:
-
请注意,生成的调试符号和生成的优化实际上是正交的。同时打开调试符号和优化是合法的,尽管有些不寻常。可能需要仔细检查您是否处于那种奇怪的配置中。
-
对于我的活动 (Debug/x64) 配置,未选中“构建”选项卡下的“优化代码”复选框。我应该检查其他地方吗?
-
不;听起来这不是问题。
-
刚刚尝试过(关闭优化代码,开启调试)并可以看到所描述的行为 - 在 x86 中,直接在 SomeData != null 行之后,而在 x64 中,它在第一次访问时“变为!= null”(不是来自调试器,而是在代码中)......比较生成的 IL 的样子可能会很有趣......
-
@Jeff:听起来确实是一个错误,但我没有复制它,所以我无法确认。听起来像是在 Connect 上发帖的好人选。我不知道是否已经有一个案例。我注意到多年来有许多奇怪的错误涉及条件运算符的代码生成和调试。用于静态确定堆栈槽的已知类型的精确 CLR 规则可能有点棘手,并且会导致错误。如果这是其中的另一个,我不会感到惊讶,但就像我说的,我没有亲自复制它。
标签: c# visual-studio-2010 ternary-operator