首页 > 解决方案 > foreach 循环变量抛出 NullReferenceException 但 Enumerable 不为空

问题描述

有些人决定关闭我之前的问题,但他们链接的问题(什么是 NullReferenceException,以及如何解决它?)没有答案。这个问题是根本不同的,因为枚举是填充的。它不为空。正如第一个答案所说,我放置了“战略断点”并检查了变量。

我正在调试 XUnit 测试,结果发现在我的业务逻辑中,foreach 循环中的迭代变量引发了异常“对象引用未设置为对象实例”。但是,发生迭代的列表不为空。我在调试时可以看到。这是代码:

商业逻辑:

List<string> regionArray = new List<string>();
if (someCondition)
{
    regionArray = _utils.GetRegions(someParam); // this is not returning null
}
foreach (var region in regionArray)
{
      var query = from dataSet in myDataSets
                  where dataSet.Location == region
                  select dataSet;
      var queryResult = query.FirstOrDefault();
      if (queryResult == null)
      {
           // do stuff
      } else if (queryResult.State != States.Provisioned)
      {
           // do stuff
      }
}

这是我嘲笑_utils.GetRegions电话的方式,但我认为这不是问题所在。

private Mock<IUtils> _mockRegionUtils;

[Fact]
public void ItWorks()
{
    // do stuff
    _mockRegionUtils = new Mock<IUtils>();
    _mockRegionUtils.Setup(utils => utils.GetRegions(It.IsAny<ISomeParam>())).Returns(new List<string>() {"america", "china"});
    // call business logic
}

我已经检查了调试器中的所有类型。regionArray.GetType()返回{System.Collections.Generic.List`1[System.String]}。但是,当我在控制台中键入区域时,我得到:

region
'region' threw an exception of type 'System.NullReferenceException'

这怎么可能?

编辑:修正了上面的错字,对此感到抱歉。不过有些奇怪,所以如果我将值重新分配为regionArray内联列表,它仍然会失败。但是,如果我定义一个新的内联列表并对其进行迭代,则循环工作正常。

List<string> regionArray = new List<string>();
if (someCondition)
{
    regionArray = _utils.GetRegions(someParam); // this is not returning null
}
regionArray = new List<string>() {"china", "america"};
List<string> temp = new List<string>() {"foo", "bar"}
foreach (var region in regionArray)
{
      // region still throws null reference exception
      foreach (var tempVar in temp)
      {
          var c = tempVar; // this works. tempvar is never null.
      }
      var query = from dataSet in myDataSets
                  where dataSet.Location == region
                  select dataSet;
      var queryResult = query.FirstOrDefault();
      if (queryResult == null)
      {
           // do stuff
      } else if (queryResult.State != States.Provisioned)
      {
           // do stuff
      }
}

regionArray编辑2:所以我尝试在上面的逻辑之前以相同的方式迭代,它工作得很好。

List<string> regionArray = new List<string>();
if (someCondition)
{
    regionArray = _utils.GetRegions(someParam); // this is not returning null
}

foreach (var region in regionArray)
{
      var c = region; // this works
}

foreach (var region in regionArray)
{
      // region throws null reference exception
      var query = from dataSet in myDataSets
                  where dataSet.Location == region
                  select dataSet;
      var queryResult = query.FirstOrDefault();
      if (queryResult == null)
      {
           // do stuff
      } else if (queryResult.State != States.Provisioned)
      {
           // do stuff
      }
}

所以最有可能的是,起订量对象不是问题。根据@Iliar 的建议,我会看看是否regionArray被修改,但乍一看,因为 regionArray 没有在循环中使用,我的回答是“否”。

标签: c#.netmoq

解决方案


更新:我通过将region循环变量重命名为不同的名称来解决这个问题。事实证明,我foreach (var region ...)在代码的前面做了另一个循环。我与一些高级同事讨论了为什么这两个名称会相互冲突,他们说这可能是 VSCode 中的符号有问题,而不是我的实际代码。谢谢大家的帮助!

这个线程中有很多信息,所以在这里总结一下是一些要点,以防将来对其他人有帮助:

  • 在调试 XUnit 测试时,我看到我的 foreach 中的循环变量在 tooltip 中显示以下信息'region' threw an exception of type 'System.NullReferenceException' Data [IDictionary]:{System.Collections.ListDictionaryInternal} HResult [int]:-2147467261 HelpLink [string]:null InnerException [Exception]:null Message [string]:"Object reference not set to an instance of an object." Source [string]:"9dd66c33104045bba27ad3fc9fb95185" StackTrace [string]:" at <>x.<>m0(<IngestEvents>d__13 <>4__this)" TargetSite [MethodBase]:{System.String <>m0(<IngestEvents>d__13)} Static members ...

  • 即使我进入循环,工具提示region仍然显示上述内容,当我输入region控制台时,我得到了'region' threw an exception of type 'System.NullReferenceException'.

  • 以上两点让我相信region是空的。但是,通过@IVSoftware 的帮助,我验证了它region实际上不是空的,因为断言正在通过。

  • 然后我查看了我的其余代码,作为随机猜测,我尝试将循环变量重命名region为其他内容。当我这样做时,region被正确设置为列表的元素。

推荐阅读