您当前的位置: 首页 > 

寒冰屋

暂无认证

  • 1浏览

    0关注

    2286博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

如何避免在迭代集合为 null 时抛出的空引用异常?

寒冰屋 发布时间:2022-02-10 19:00:00 ,浏览量:1

咨询区
  • Polaris878

我在遍历集合时,经常会遇到集合为 null 的情况,比如下面这样:

int[] returnArray = Do.Something(...);

拿到数组后,接下来我用下面的方式进行遍历。

foreach (int i in returnArray)
{
    // do some more stuff
}

说实话,我非常好奇,为什么就不能在 null 集合中进行迭代呢?我觉得从逻辑上来说,null集合意味着没有迭代项而已,但框架却抛出了 NullReferenceException 异常,真的难以理解。

真的很让我苦恼,每次在调用 api 的时候我也不清楚对方确切返回值,只能每次都用 if (someCollection != null) 做一个前置判断。

回答区
  • Reed Copsey

首先你要明白 空集合 和 null 有着本质的区别,foreach 在内部调用的是 IEnumerable 的 GetEnumerator() 方法,而 null 哪里有呢?自然就会引发 NullReferenceException 异常,不是吗?

要想解决,方法也挺多的,大概有如下几种。

1、Enumerable.Empty()

Empty()扩展方法的内部是一个 EmptyPartition 类,它的 MoveNext() 直接返回 false,是空集合的绝佳替代方案,源码如下:

internal sealed class EmptyPartition
{
 public bool MoveNext()
 {
  return false;
 }
}

在使用上,非常推荐封装为一个扩展方法。

public static IEnumerable AsNotNull(this IEnumerable original)
{
     return original ?? Enumerable.Empty();
}

foreach (int i in returnArray.AsNotNull())
{
    // do some more stuff
}

2、使用 ?. 可空运算符

空检查操作符 ?. 也是一个非常好的方式,参考如下代码:

        //fragments is a list which can be null
        fragments?.ForEach((obj) =>
        {
            //do something with obj
        });

3、封装 action

可以将 foreach 中的迭代逻辑封装到 action 中,并在扩展方法上做防御性检查即可,参考如下代码:

public static class Extensions
{
   public static void ForEachWithNull(this IEnumerable source, Action action)
   {
      if(source == null)
      {
         return;
      }

      foreach(var item in source)
      {
         action(item);
      }
   }
}

点评区

这确实是一个很搞的问题,相信很多朋友在项目开发中肯定会遇到,设计模式也有类似的 空对象模式,大佬提供的这三种方式很不错,学习了。

关注
打赏
1665926880
查看更多评论
立即登录/注册

微信扫码登录

0.0446s