我得到一个奇怪的NullReferenceException,在尝试模拟集合进行枚举时我无法理解。我不认为这是由Mock引起的任何事情,但我并非100%肯定。任何人都可以发现我正在做的任何愚蠢行为吗?
InfoDataSet<OrderItemInfo> orders = OrderItemInfoProvider.GetOrderItems(orderInfo.OrderID);
foreach (OrderItemInfo orderItem in orders)
{
// Exception thrown on the first attempt to get an OrderItem in the foreach
}
此代码行的堆栈跟踪如下:
System.NullReferenceException:未将对象引用设置为实例
一个对象。结果StackTrace:在 CMS.SettingsProvider.ObjectDataSet1.GetEnumerator() at
1.GetObjectEnumerator()在
CMS.SettingsProvider.ObjectDataSet
CMS.SettingsProvider.InfoDataSet`1.d__0.MoveNext()
在......
集合的内容只是IEnumerable的包装器。在我的情况下,这应该让你知道发生了什么。 GetEnumerator(隐式和非隐式)实现只需调用值。
private IEnumerable<T> values;
/// <summary>
/// Initializes a new instance of the <see cref="MockDataSet{T}"/> class.
/// </summary>
/// <param name="values">The values.</param>
public MockDataSet(IEnumerable<T> values)
{
if (values == null)
throw new ArgumentNullException("values");
this.values = values;
}
值中有一个值,我可以通过监视窗口枚举...
有谁能解释我在这里做错了什么?
答案 0 :(得分:1)
这有点奇怪,我认为部分归结为下面的CMS(Kentico)。我之前遇到过一个问题,我在Unable to call ToArray() on 3rd party class上发了一个问题,我才意识到这可能会产生同样的影响。
似乎InfoDataSet<OrderItemInfo> orders = OrderItemInfoProvider.GetOrderItems(orderInfo.OrderID);
的结果很难让编译器确定其类型。因此,我认为演员阵容正在下面说
((IEnumerable<OrderItemInfo>)orders)
我认为这是失败的,导致IEnumerable为null,因此NullReferenceException。决议是每个项目的简单演员:
InfoDataSet<OrderItemInfo> orders = OrderItemInfoProvider.GetOrderItems(orderInfo.OrderID);
foreach (OrderItemInfo orderItem in orders.Cast<OrderItemInfo>())
{
// Now works
}
答案 1 :(得分:0)
orders
为空。你认为这不是因为循环已经开始但是记住它被评估为懒惰。
更改这样的代码,它不会失败:
InfoDataSet<OrderItemInfo> orders = OrderItemInfoProvider.GetOrderItems(orderInfo.OrderID);
if (orders != null)
{
foreach (OrderItemInfo orderItem in orders)
{
// Exception thrown on the first attempt to get an OrderItem in the foreach
}
}
请记住,每当您在调试器中查看某些内容时,周期时间已经过了很长时间 - 如果您有任何异步更新,它可能还没有完成。