更好的方法来检查列表中的元素
本文关键字:元素 列表 方法 更好 检查 | 更新日期: 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实现至少有一个元素(例如,由GroupBy
或ToLookup
生成的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
不需要选中Count
。Max
需要值类型的非空列表,但可以通过内联强制转换来克服,例如
int? max = new List<int>().Max(i => (int?)i); // max = null