更好的方法来检查列表中的元素

本文关键字:元素 列表 方法 更好 检查 | 更新日期: 2023-09-27 18:14:12

如果我想执行诸如。where(…)或。max(…)之类的操作,我需要确保列表不为空并且计数大于零。除了每次我想使用列表时做以下事情之外:

if(mylist != null && mylist.Count > 0)
{...}

是否有更多的内联或类似lambda的技术,我可以使用?或者另一种更压缩的技术?

更好的方法来检查列表中的元素

public static class LinqExtensions
{
     public static bool IsNullOrEmpty<T>(this IEnumerable<T> items)
     {
           return items == null || !items.Any();
     }
}

你可以这样做

if (!myList.IsNullOrEmpty())
 ....

我的一般偏好是使用空列表实例,而不是空列表变量。然而,并不是每个人都能说服他们的同事这样做。您可以使用这个扩展方法来保护自己免受空列表变量的影响。

public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> source)
{
  return source ?? Enumerable.Empty<T>();
}

调用:

Customers result = myList.EmptyIfNull().Where(c => c.Name == "Bob");

大多数linq方法工作在空集合上。两个方法不是最小和最大。通常,我针对igrouing调用这些方法。大多数IGroupings实现至少有一个元素(例如,由GroupByToLookup生成的IGroupings)。对于其他情况,可以使用Enumerable.DefaultIfEmpty

int result = myList.EmptyIfNull().Select(c => c.FavoriteNumber).DefaultIfEmpty().Max();

不要让list为空

确保对象始终处于有效状态。通过确保列表不为空,您就不必检查列表是否为空。

public class MyClass
{
    private readonly IEnumerable<int> ints;
    public MyClass(IEnumerable<int> ints)
    {
        this.ints = ints;
    }
    public IEnumerable<int> IntsGreaterThan5()
    {
        return this.ints.Where(x => x > 5);
    }
}

即使这个列表是空的,您仍然会得到一个有效的IEnumerable<int>

可空类型的最大和最小重载

这仍然不能解决"最大值"answers"最小值"的问题。有一个重载的Max和Min,它们接受选择器。这些选择器重载可以返回可空的整型,所以你的max方法变成这样:

this.ints.Max(x => new int?(x));

因此,运行Max并检查返回的是空值还是整数。瞧!

其他选择

自定义扩展方法

您也可以编写自己的扩展方法。

public static MinMaxHelper()
{
    public static int? MaxOrDefault(IEnumerable<int> ints)
    {
        if(!ints.Any())
        {
            return null;
        }
        return ints.Max();
    }
    public static int MaxOrDefault(IEnumerable<int> ints, int defaultValue)
    {
        if(!ints.Any())
        {
            return defaultValue;
        }
        return ints.Max();
    }
}

重写Linq扩展方法

最后,请记住,内置的Linq扩展方法可以被您自己的具有匹配签名的扩展方法覆盖。因此,您可以编写一个扩展方法来替换。where(…)和。max(…)以返回null(或默认值),而不是在Enumerable为null时抛出ArgumentNullException。

使用empty集合而不是null集合。Where可以很好地处理空集合,因此您不需要在调用Count > 0之前确保它。如果您先做一些操作,也可以在空集合上调用Max

对于IEnumerable<T>使用Enumerable.Empty<T>()

对于T[]使用new T[0]

对于List<T>使用new List<T>()

您可以尝试myList.Any()而不是.Count,但您仍然需要检查null

如果存在列表为空的风险,则必须在调用其任何方法之前进行检查,但您可以使用any()方法而不是count。无论列表中是否有一个或多个项目,只要计数到一个项目,就会返回true。这节省了遍历整个列表的时间,而这正是Count要做的:

if(mylist != null && mylist.Any())
{...}

你可以使用??将null转换为您在右侧提供的值的操作符:

public ProcessList(IEnumerable<int> ints)
{
    this.ints = ints ?? new List<int>();
}

顺便说一下:使用LINQ处理空列表是没有问题的。

调用Where不需要选中CountMax需要值类型的非空列表,但可以通过内联强制转换来克服,例如

int? max = new List<int>().Max(i => (int?)i); // max = null