【问题标题】:Testing for 'lazy loaded' null IEnumerable in c#?在 C# 中测试“延迟加载”空 IEnumerable?
【发布时间】:2017-04-11 08:21:16
【问题描述】:

我已经简化了一段延迟执行代码,但是如果不将其包装在 try/catch 中,您究竟如何检查以下内容是否为空/空?

    string[] nullCollection = null;
    IEnumerable<string> ienumerable = new[] { nullCollection }.SelectMany(a => a);

    bool isnull = ienumerable == null; //returns false
    bool isany = ienumerable.Any(); //throws an exception

【问题讨论】:

  • @MrinalKamboj 这是一个 NullReferenceException 抛出,因为 SelectManyIterator 是用一个空元素调用的。
  • @RB。那么它很棘手,我以上几点都不成立

标签: c# linq ienumerable


【解决方案1】:

您只需要使您的 lambda 对空条目更具弹性:

IEnumerable<string> ienumerable = new[] { nullCollection }
    .SelectMany(a => a ?? Enumerable.Empty<string>());

bool isany = ienumerable.Any(); // Sets isany to 'false'

【讨论】:

  • 这很好,但如果我只是通过了 IEnumerable&lt;string&gt; 参数,我想我会被卡住......
  • @maxp 是的 - ienumerable 的构造存在根本问题。我认为没有任何解决办法。
【解决方案2】:

您不能这样做,因为这与问“我怎么知道该方法不会在不调用 NullReferenceException 的情况下抛出它?”是一样的。没有其他线索,唯一的方法就是调用这些方法并观察结果。枚举IEnumerable 只是在它的枚举器上调用一堆MoveNext 调用,任何这样的调用都可能引发任何异常。

【讨论】:

    【解决方案3】:

    您可以检查枚举器中的当前项是否为空

    string[] nullCollection = null;
    IEnumerable<string> ienumerable = new[] { nullCollection }.SelectMany(a => a);
    
    bool isnull = ienumerable.GetEnumerator().Current == null;
    if (!isnull)
    {
        bool isany = ienumerable.Any();
    }
    

    【讨论】:

    • 这不起作用 - 当您调用 MoveNext() 进行迭代时,如果遇到 null 元素,它将崩溃。最终,投影函数将针对每个元素进行评估,当使用空值调用它时会导致崩溃 - 我认为没有任何解决办法。
    • @RB。没有MoveNext(),没有Current :)。是不是又回到了方位
    • 这是一个完全错误的答案——在MoveNext 之前访问Current 有未定义的行为——很可能在这里它总是返回null
    • @IvanStoev 我说过:)
    • @MrinalKamboj 是的 - 我认为我们都以略有不同的方式说了同样的话 :)
    【解决方案4】:

    由于 Linq 方法是 IEnumerable 上的扩展方法,您可以进一步包装这些扩展:使用扩展方法,接收扩展的对象可以为 null。

        public static IEnumerable<TResult> SafeSelectMany<T, TCollection, TResult>(
                this IEnumerable<T> source, 
                Func<T, IEnumerable<TCollection>> collectionSelector, 
                Func<T, TCollection, TResult> resultSelector)
        {
            if (source == null)
            {
                return null;
            }
            IEnumerable<TResult> result = source.SelectMany(collectionSelector, resultSelector);
            return result;
        }
    

    您也可以为source==null 返回一个空的List&lt;TResult&gt; 而不是null

    【讨论】:

      猜你喜欢
      • 2018-06-24
      • 1970-01-01
      • 2021-04-21
      • 2021-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-26
      • 2021-05-06
      相关资源
      最近更新 更多