尝试枚举自定义类型的列表时引发异常



我有两个通过JSON反序列化填充的列表

List<MyType> a = JsonConvert.DeserializeObject<List<MyType>>(jsonstringa);
List<MyType> b = JsonConvert.DeserializeObject<List<MyType>>(jsonstringb);

然后,我对每一个进行迭代,并执行一些逻辑。这些藏品可能是空的,这是完全合理的。

foreach (MyType myA in a)
{
   //DO STUFF HERE
}
foreach (MyType myB in b)
{
   //DO STUFF HERE
}

当集合中有任何一个的项时,都没有问题。然而,当列表B中没有项目时,我会在"foreach"行上得到一个"Object reference not set to a instance of a Object"Exception。但是,列表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为空,myB.Count将引发异常。你应该先检查空:

if(myB != null && myB.Count > 0)

为了安全起见,你可能还想对你的第一份清单这样做。。。您可以取消Count检查,这是不必要的。如果集合为foreach不会抛出异常,它只在您尝试迭代null集合时抛出,因为foreach在您的集合上调用GetEnumerator方法,这会导致异常。

如果ab为null,则不能对其调用函数。您将获得null引用异常。所以请检查它们是否为空。

if(a !=null)
{
    foreach (MyType myA in a)
    {
       //DO STUFF HERE
    }
}

不需要在foreach表达式之前检查计数。如果它是空的,那么它基本上跳过循环。

问题在于您假设ab永远不是null。如果输入不是json,或者在结构上与您的类型的定义有很大不同,那么这些引用将为null,然后当您尝试迭代null时,您将崩溃。

您只需要为每个集合使用if ( a != null ) // iterate,因此,您应该在从DeserializeObject<T> 分配的任何时候进行无效性检查

不能对null集合进行迭代,因为foreach将对提供的IEnumerable参数隐式调用GetEnumerator()。在foreach子句中使用默认值之前,必须为b指定一个默认值,或者检查它是否不是null

if ((b != null) && (b.Count > 0)) 
{
    foreach (MyType myB in b)
    {
       //DO STUFF HERE
    }
}

因为我不知道jsonstringa的值或jsonstringb的值是什么。我猜jsonsringb将是一个空字符串,因为你指的是没有项的情况。空字符串将被视为格式错误的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);

在循环或调用列表上的方法之前,不要忘记检查null。

if (b!=null){
//Your loop or Count here!
};

另一种检查集合是否有元素的方法是使用any()而不是Count。

if(b.Any()){
//you have elements in b
}

最新更新