C# Linq如何实现带自定义默认值的FirstOr方法?
实现自定义默认值的FirstOr方法
要实现支持自定义默认值的FirstOr方法,最直接的方式是给IEnumerable<T>编写扩展方法,和Linq原生方法的风格对齐。我们需要实现两个重载:一个不带筛选条件,直接返回序列第一个元素或自定义默认值;另一个带筛选条件,返回第一个符合条件的元素或自定义默认值。
1. 无筛选条件的FirstOr
先处理最基础的场景:如果序列有元素,返回第一个;如果为空,返回传入的自定义默认值。
public static class EnumerableExtensions { public static T FirstOr<T>(this IEnumerable<T> source, T defaultValue) { // 校验参数合法性,避免空引用 if (source == null) throw new ArgumentNullException(nameof(source)); foreach (var item in source) { // 找到第一个元素直接返回,无需遍历整个序列 return item; } // 序列为空时返回自定义默认值 return defaultValue; } }
这里直接用foreach遍历,找到第一个元素就返回,比先调用Any()再调用First()更高效(避免两次遍历序列),同时也不会出现“序列中第一个元素刚好是类型默认值时误返回自定义值”的问题。
2. 带筛选条件的FirstOr
再实现带筛选逻辑的重载,和原生First(predicate)对应:
public static class EnumerableExtensions { // 上面的无参重载也放在这个类里 public static T FirstOr<T>(this IEnumerable<T> source, Func<T, bool> predicate, T defaultValue) { // 校验参数 if (source == null) throw new ArgumentNullException(nameof(source)); if (predicate == null) throw new ArgumentNullException(nameof(predicate)); foreach (var item in source) { if (predicate(item)) { return item; } } // 没有符合条件的元素时返回自定义默认值 return defaultValue; } }
使用示例
写完扩展方法后,就可以像用Linq原生方法一样调用:
// 示例1:空序列返回自定义默认值 var emptyList = new List<int>(); var result1 = emptyList.FirstOr(-1); // 结果为-1 // 示例2:非空序列返回第一个元素 var numbers = new List<int> { 1, 2, 3 }; var result2 = numbers.FirstOr(-1); // 结果为1 // 示例3:带筛选条件,没找到符合条件的元素返回自定义值 var strings = new List<string> { "apple", "banana" }; var result3 = strings.FirstOr(s => s.StartsWith("c"), "Not Found"); // 结果为"Not Found"
为什么不用FirstOrDefault+判断?
有人可能会想,直接用source.FirstOrDefault() ?? defaultValue?但这种写法有问题:如果序列中第一个元素刚好是值类型的默认值(比如int的0),或者引用类型的null,就会错误地返回自定义默认值,而不是序列本身的元素。所以直接遍历的方式更可靠。
内容的提问来源于stack exchange,提问作者pete
相关产品推荐
相关产品推荐

