0

所以,我有一段使用 Wea​​kReferences 的代码。我知道常见的.IsAlive比赛条件,所以我没有使用它。我基本上有这样的东西:

WeakReference lastString=new WeakReference(null);
public override string ToString()
{
  if(lastString!=null)
  {
    var s=lastString.Target as string; //error here
    if(s!=null)
    {
      return s;
    }
  }
  var str=base.ToString();
  lastString=new WeakReference(str);
  return str;
}

不知何故,我在标记的行处得到了一个空引用异常。通过调试它,我可以确认 lastString 确实为 null,尽管它包含在 null 检查中并且 lastString 实际上从未设置为 null。

这也只会发生在复杂的流程中,这让我认为垃圾收集以某种方式获取了我的实际 WeakReference 对象,而不仅仅是它的目标。

有人可以告诉我这是如何发生的以及最好的行动方案是什么?

编辑:我完全无法确定造成这种情况的原因。我最终将错误代码包装在 try-catch 中,暂时修复它。不过,我对此的根本原因非常感兴趣。我一直试图在一个简单的测试用例中重现这一点,但事实证明这很难做到。此外,这似乎只在单元测试运行器下运行时才会发生。如果我把代码修剪到最小,它会在使用 TestDriven 和 Gallio 运行时继续崩溃,但在放入控制台应用程序时不会失败

4

1 回答 1

1

这最终成为一个非常难以发现的逻辑错误。

令人讨厌的 if 语句实际上更像是这样的:

if(lastString!=null && limiter==null || limiter=lastLimiter)

真正的分组更像是这样的:

if((lastString!=null && limiter==null) || limiter=lastLimiter)

正如墨菲定律以某种方式规定的那样,在这个不相关的测试用例中,lastLimiterlastString通过一种仅在这个单一测试用例中使用的方法设置为空。

所以,是的,CLR 中没有错误,只是我自己很难发现的逻辑错误

于 2013-07-03T14:26:46.113 回答