foreach循环变量抛出NullReferenceException但Enumerable不为空

问题描述 投票:-1回答:1

某些人决定结束我的上一个问题,但是他们链接的问题(What is a NullReferenceException, and how do I fix it?)没有答案。这个问题从根本上有所不同,因为可枚举已填充。不为空。就像第一个答案所说的那样,我放置了“战略断点”并检查了变量。

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

业务逻辑:

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
'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
      }
}

编辑2:因此,我尝试以与上述逻辑之前相同的方式遍历regionArray,并且工作正常。

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
      }
}

最有可能的是,moq对象不是问题。基于@Iliar的建议,我将查看regionArray是否被修改,但是乍一看,由于在循环中未使用regionArray,因此我的回答是“否”。

c# .net moq
1个回答
0
投票

嗨,我真的希望能对您有所帮助。首先,我将回答您的问题“这怎么可能?”而且我想我可以解释为什么带内联列表的已编辑问题有效。正确,GetRegions方法返回一个不为null的列表。当然,如果您对此调用GetType(),它将正确地将其标识为“字符串列表”。但是,我相信GetRegions方法返回的列表至少包含一个null value。您可以在添加编辑内容时亲自证明这一点,因为您说这可行:

regionArray = new List<string>() {"china", "america"};

但是尝试使用这样的三个值创建列表,其中三个值之一为空,并且循环可能再次失败。

regionArray = new List<string>() {"china", null, "america"};

这表明GetRegions方法内部的错误是将空值放入要返回的列表中。在循环的开头添加这两行可能会大大帮助您找出问题所在:

        foreach (var region in regionArray)
        {
            // Look for this in the Visual Studio 'Output' window 
            System.Diagnostics.Debug.WriteLine(region == null ? "Null" : region);
            // You believe that region is not null. So 'assert' that 
            // this evaluates to True and if it doesn't the debugger will break here.
            System.Diagnostics.Debug.Assert(region != null, "Break on this line if region is null");
    ...

据我所知,我将查看您的GetRegions(someParam)方法内部,看看它是否在列表中的某个位置插入了null。祝你好运!

© www.soinside.com 2019 - 2024. All rights reserved.