当我在整数或布尔值的空列表上使用 FirstOrDefault()
时,我得到 0
或 false
而不是 null
。
我知道这是设计使然,因为它返回 default(T)
,但我如何强制它返回 null
?
var emptyList = new List<int>();
emptyList.FirstOrDefault() == 0; // I want to receive null instead
答案 0 :(得分:2)
这就是它被称为 FirstOrDefault
而不是 FirstOrNull
的原因。后者意味着在值类型(T
与 Nullable<T>
)的情况下,返回类型将与元素类型不同。
(我看到你已经回答了你自己的问题,所以我只是用 FirstOrNull
扩展方法作为通用解决方案来完成它):
// the generalized version of Bouke's answer for the problem:
public static T? FirstOrNull<T>(this IEnumerable<T> source)
where T : struct
=> source.Cast<T?>().FirstOrDefault();
当然,如果性能很重要,您可以进一步改进它:
public static T? FirstOrNull<T>(this IEnumerable<T> source)
where T : struct
{
// Shortcuts for special cases. FirstOrDefault also has something like this
// (but it's not quite useful on the enumerator returned by Cast<T>)
if (source is ICollection<T> collection)
{
if (collection.Count == 0)
return null;
if (collection is IList<T> list)
return list[0];
}
// general solution
using var enumerator = source?.GetEnumerator() ?? throw new ArgumentNullException(nameof(source));
return enumerator.MoveNext() ? enumerator.Current : default(T?);
}
答案 1 :(得分:1)
要使 FirstOrDefault()
、LastOrDefault()
或 SingleOrDefault()
返回 null 作为 values 列表中的默认值(而不是 < em>引用):
使用 IEnumerable<T>.Cast<T?>()
将您的元素转换为 nullable。
var emptyList = new List<int>();
emptyList.FirstOrDefault() == 0;
emptyList.Cast<int?>().FirstOrDefault() == null;
IEnumerable<T>.FirstOrDefault()
将在没有结果时返回 default(T)
。
default(T)
,例如对于 int
将是 0
null
,作为 default(int?) == null
。答案 2 :(得分:0)
如果您不想使用 Nullable
public static T? FirstOrNull<T>(this IEnumerable<T> collection, Predicate<T> validator = null)
where T : struct {
foreach (var item in collection) {
if (validator?.Invoke(item) != false) {
return item;
}
}
return default;
}
//invocations
int[] list = new int[0];
int? match = list.FirstOrNull(); // => null
list = new [] { 1, 2, 3, 4, 5, 6 };
match = list.FirstOrNull(i => i == 42); // => null
match = list.FirstOrNull(); // => 1
match = list.FirstOrNull(i => i % 3 == 0); // => 3