某些人决定结束我的上一个问题,但是他们链接的问题(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,因此我的回答是“否”。
嗨,我真的希望能对您有所帮助。首先,我将回答您的问题“这怎么可能?”而且我想我可以解释为什么带内联列表的已编辑问题有效。正确,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。祝你好运!