我见过的最奇怪的错误

3
我有一个无法解释的情况。请查看以下代码,并注意变量 c 和 d 的定义及其奇怪的值。 c 等于null,但 d 不是。鉴于我百分之百确定以下几点,这肯定是不可能的(对吧?):
  • a.value是一个字段,而不是属性
  • 类型限定符是封闭的引用类型,具有基础类型对象
  • 应用程序仅为单线程。
  • 我已经执行过“清理解决方案”。
现在最奇怪的事情是,当我停止调试运行时,将底部行的lambda表达式中的变量 c 替换为 d ,然后再次构建和运行时, d 即为 null ,但 c 却不是!
private static object CreateConstraints(CompositeElement constraintsElement)
{
    Contract.Requires(constraintsElement != null);

    var constraintTypes = from e in constraintsElement where e.DefinitionName.IsAnyOf("ConstraintType", "ConstraintTypeNamePrependedWithComma") select (Qualifier)e.Value;
    var declarer = (MemberDeclaration)constraintsElement.Parent.Value;
    GenericTypeParameterCollection genericTypeParameters = declarer.Name.Suffixes.OfType<GenericTypeParameterCollection>().First();

    Element a = constraintsElement["TypeName"];
    a.SetValue();
    var c = a.value as Qualifier;
    var d = a.value as Qualifier;

    genericTypeParameters.First(gp => gp.Type == c).Constraints.AddRange(constraintTypes);

    return null;
}

我还制作了两次运行的反汇编 截图。个人认为我不确定它们是否有误。

因此,我想问一下是否我漏掉了什么可以使这种行为完全正常,或者这里真的有一些非常奇怪的东西?


好的,代码已经粘贴了。现在你必须相信我说c是null而d不是。在图像中,你可以看到在本地窗口中... - JBSnorro
1
这是已删除的图片:http://i.stack.imgur.com/mr0QT.png - Paul Ruane
@Jason,用 ReferenceEquals(gp.Type, c) 或者 ReferenceEquals(gp.Type, d) 替换 gp.Type == c 实际上在本地窗口中并没有改变任何内容... - JBSnorro
2
@JBSnorro:嗯,本地窗口似乎认为有两个名为“c”的变量(或者根据lambda表达式中的内容是“d”)。请按照以下步骤操作。从“var c = a.value as Qualifier;”中删除“c”。将其命名为“foo”。现在将“foo”复制并粘贴到lambda表达式中。重复此过程,处理“d”。会发生什么? - jason
@JBSnorro:那么这一定是个bug。在Microsoft Connect上发布。 - jason
显示剩余10条评论
3个回答

2

虽然我可能有点傻,但是我并没有看到问题。

  • 从描述中看,没有“错误”。(或者你的程序逻辑出了问题吗?)
  • 我们只是在调试器窗口中看到一个变量c出现了两次。
  • c的一个实例具有正确的类型(我假设它也有正确的值)。
  • 另一个实例是空的。这必须是捕获的c的视图,由于lambda表达式没有执行,因此它是null

那么问题应该是什么呢?

您可以尝试在lambda表达式内部设置断点。


问题在于我没有看到第二个 c,这意味着将同一实例(a.value)分配给两个不同的局部变量会产生不同的结果... 但事实上,唯一的真正问题是一个变量在本地窗口中出现了两次。尽管如此,在调试时,这让我走了完全错误的方向,因为我得出了一些不可能发生的结论(c != d)。无论你怎么看,这仍然是一个 bug。 - JBSnorro
一个简单的 Debug.Assert(c == d); 可以让事情变得清晰明了。 - H H
是的,但为什么我会考虑这样的断言呢?当我已经从本地窗口得出c!=d时,我甚至没有考虑过c==d,直到我知道第二个c - JBSnorro
2
当您看到冲突/混淆的信息时,请寻找第二个来源并尝试验证。 - H H

1

从您编辑前的调试器截图中看到,我注意到本地变量“c”列出了两次,一次为空值,一次作为限定符实例的值。这似乎很奇怪,并让我怀疑C#编译Lambda表达式时存在错误。作为解决方法,请尝试使用显式委托。

此外,在Lambda表达式中的双等号上有一个错误标记。将鼠标悬停在上面以获取错误消息可能会提供发生了什么的线索。


请允许异步发布的特性。当我在查看您的问题并编写答案时,我没有看到所有的评论。 - JGWeissman

0
也许在调用堆栈深处抛出了异常,并且异常处理的方式阻止了赋值的正确执行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接