C# 尝试枚举自定义类型的列表时引发异常
我有两个通过JSON反序列化填充的列表C# 尝试枚举自定义类型的列表时引发异常,c#,asp.net,entity-framework,asp.net-mvc-4,nullreferenceexception,C#,Asp.net,Entity Framework,Asp.net Mvc 4,Nullreferenceexception,我有两个通过JSON反序列化填充的列表 List<MyType> a = JsonConvert.DeserializeObject<List<MyType>>(jsonstringa); List<MyType> b = JsonConvert.DeserializeObject<List<MyType>>(jsonstringb); 如果其中一个的集合中有项目,则不会出现问题。但是,当列表B中没有项目时,我会在“for
List<MyType> a = JsonConvert.DeserializeObject<List<MyType>>(jsonstringa);
List<MyType> b = JsonConvert.DeserializeObject<List<MyType>>(jsonstringb);
如果其中一个的集合中有项目,则不会出现问题。但是,当列表B中没有项目时,我会在“foreach”行上抛出一个“objectreference not set to a instance of a Object”异常。但是,列表A不会出现这种情况
为了安全起见,我进一步修改了上述代码,使其看起来如下所示:
if (a.Count > 0)
{
foreach (MyType myA in a)
{
//DO STUFF HERE
}
}
if (b.Count > 0)
{
foreach (MyType myB in b)
{
//DO STUFF HERE
}
}
无论是空集合还是包含元素,通过“A”列表的迭代都可以正常进行。如果集合中有元素,则通过“B”列表的迭代再次正常进行,但再次抛出相同的异常,但这次在(myB.Count)>0
行除外。通过调试,两个集合的Count属性在集合为空时显示“0”(如我所料)
自定义“MyType”类有一个默认构造函数,其中所有非虚拟变量都声明为:
namespace MyApp.Models
{
public class MyType
{
public int ID { get; set; }
public string Code { get; set; }
public int ParentID { get; set; }
[ScriptIgnore(ApplyToOverrides = true)]
[JsonIgnore]
public virtual Parent Parent { get; set; }
public MyType()
{
ID = 0;
Code = null;
ParentID = 0;
}
}
}
我有点不知所措。我还有其他自定义类型在这里也失败了,但是,我怀疑这种相同类型的配对,其中一个通过得很好,另一个抛出异常,希望能帮助有人给我一些关于这种行为的见解。如果
myB
为nullmyB.Count
将抛出异常。您应该首先检查null:
if(myB != null && myB.Count > 0)
为了安全起见,您可能还希望在第一个列表中执行此操作……并且您可以删除
计数检查,这是不必要的。foreach
在集合为空时不会引发异常,它仅在您尝试迭代null集合时抛出,因为foreach
调用集合上的GetEnumerator
方法导致异常。如果a
或b
为null,则无法对其调用函数。您将得到一个空引用异常。所以检查它们是否为空
if(a !=null)
{
foreach (MyType myA in a)
{
//DO STUFF HERE
}
}
无需在foreach
表达式之前检查计数。如果它是空的,那么它基本上跳过了循环。问题在于您假设a
和b
从来都不是null
。如果输入不是json,或者在结构上与您的类型的定义有很大差异,那么这些引用将为null,然后当您尝试在null上迭代时,您将崩溃
如果(a!=null)//iterate
对于每个集合,您只需要执行if(a!=null)//iterate
,因此,无论何时从DeserializeObject分配,您都应该执行空值检查,因为foreach
将隐式调用GetEnumerator()
在提供的IEnumerable
参数上。在foreach
子句中使用之前,必须为b
指定一个默认值,或者检查它是否为null
if ((b != null) && (b.Count > 0))
{
foreach (MyType myB in b)
{
//DO STUFF HERE
}
}
因为我不知道jsonstringa或jsonstringb的值是什么。我猜jsonstringb将是一个空字符串,因为您指的是没有项目的情况。空字符串将被视为格式错误的JSON字符串。结果
JsonConvert.DeserializeObject
当给定一个格式错误的JSON字符串时,它将返回null而不是空列表。这意味着,如果jsonstringb格式不正确或为空字符串,则b为null。这就是为什么每当您请求b.Count或对b执行foreach(foreach将调用b上的GetEnumerator方法)时,都会得到一个null引用异常。因此,您可以执行以下操作:在调用JsonConvert.DeserializeObject之前检查jsonstringb的值,确保它不是空的或null,如果是,则将其设置为空数组
if(string.IsNullOrEmpty(jsonstringb)){
jsonstringb = "[]";
}
然后打电话
List<MyType> b = JsonConvert.DeserializeObject<List<MyType>>(jsonstringb);
检查集合是否有任何元素的另一种方法是使用any()而不是Count
if(b.Any()){
//you have elements in b
}
myB实际上是null吗?您说过“通过调试,两个集合的Count属性都显示为“0”。你的意思是你将myB.Count
定义为一个监视表达式,得到了0,但是当你继续执行时,如果(myB.Count>0)
抛出一个错误?!在上面的代码中,你不是指a.Count而不是myA.Count是列表中的一个吗?或者myA是列表中的一个吗?@JMarsch它显示为空集合,而不是通过调试显示为空集合,尽管根据下面的答案和插入一些检查,它似乎是,这解释了异常,但不是我看到的执行差异。@DadyFuji这正是我看到的,是的。你能解释为什么在这种情况下它会为空吗?当单步调试时,反序列化显示为返回空集合,而不是null,并且“myA”类型似乎就是这种情况,因此缺少异常调用。这似乎允许继续执行,但并不能解释这种异常。我不知道。似乎desialize方法返回null。因为如果集合为空,foreach不会引发异常
if (b!=null){
//Your loop or Count here!
};
if(b.Any()){
//you have elements in b
}