检查列表中元素的更好方法是什么?

时间:2011-11-09 16:48:24

标签: c# .net linq linq-to-objects

如果我想执行.Where(...)或.Max(...)等操作,我需要确保列表不为空并且计数大于零。每次我想使用列表时,除了执行以下操作之外:

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

我可以使用更多内联或lambda技术吗?还是另一种更加压缩的技术?

8 个答案:

答案 0 :(得分:9)

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

然后您可以执行类似

的操作
if (!myList.IsNullOrEmpty())
 ....

答案 1 :(得分:3)

我的首选是拥有空列表实例,而不是空列表变量。然而,并不是每个人都可以哄骗他们的同事参与这个安排。您可以使用此扩展方法保护自己免受空列表变量的影响。

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方法适用于空集合。两种方法不是Min和Max。通常,我将这些方法称为IGrouping。大多数IGrouping实现至少有一个元素(例如,由GroupByToLookup生成的IGroupings)。对于其他情况,您可以使用Enumerable.DefaultIfEmpty

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

答案 2 :(得分:2)

不要让列表为空

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

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>

Nullable类型的最大和最小重载

但仍然无法解决“Max”和“Min”问题。有选择器的Max和Min过载。那些选择器重载可以返回可为空的int,因此你的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。

答案 3 :(得分:2)

使用empty个集合代替null个集合。对于空集合,Where可以正常工作,因此在调用它之前不需要确保Count > 0。如果您先执行bit of gymnastics,也可以在空集合上调用Max

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

T[]使用new T[0]

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

答案 4 :(得分:1)

您可以尝试使用myList.Any()代替.Count,但仍需要检查null

答案 5 :(得分:1)

如果您的列表存在null的风险,您将始终在调用其任何方法之前检查它,但您可以使用Any()方法而不是count。无论列表中是否有一个或多个项目,只要计算一个项目,它就会返回true。这样可以节省整个列表的迭代次数,这将是Count将要执行的操作:

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

答案 6 :(得分:1)

你可以用??运算符,它将null转换为您在右侧提供的值:

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

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

答案 7 :(得分:1)

您无需检查Count即可致电WhereMax需要一个非空列表来表示值类型,但可以通过内联强制转换来解决,例如

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