FirstOrDefault:除null之外的默认值
据我所知,在Linq中, FirstOrDefault()
方法可以返回一个非null值的Default
值。 我没有find什么是除null以外的东西可以通过这个(和类似的)方法返回时,查询结果中没有项目。 有没有什么特别的方法可以设置,以便如果没有特定查询的值某些预定义的值作为默认值返回?
一般情况下,不只是值types:
static class ExtensionsThatWillAppearOnEverything { public static T IfDefaultGiveMe<T>(this T value, T alternate) { if (value.Equals(default(T))) return alternate; return value; } } var result = query.FirstOrDefault().IfDefaultGiveMe(otherDefaultValue);
再次,这不能真正地告诉你的序列中是否有任何东西,或者如果第一个值是默认值。
如果你关心这个,你可以做类似的事情
static class ExtensionsThatWillAppearOnIEnumerables { public static T FirstOr<T>(this IEnumerable<T> source, T alternate) { foreach(T t in source) return t; return alternate; } }
并用作
var result = query.FirstOr(otherDefaultValue);
尽pipeSteak先生指出这可以通过.DefaultIfEmpty(...).First()
。
据我所知,在Linq中,FirstOrDefault()方法可以返回一个非null值的Default值。
否。或者,它总是返回元素types的默认值。该元素types可以是空引用,可为null的值types的null值,也可以为不可为null的值types的自然“全零”值。
有没有什么特别的方法可以设置,以便如果没有特定查询的值某些预定义的值作为默认值返回?
对于参考types,您可以使用:
var result = query.FirstOrDefault() ?? otherDefaultValue;
当然这也会给你“其他默认值”,如果第一个值是存在的,但是是一个空引用…
你可以使用DefaultIfEmpty,其次是First :
T customDefault = ...; IEnumerable<T> mySequence = ...; mySequence.DefaultIfEmpty(customDefault).First();
从FirstOrDefault的文档
[返回]默认(TSource)如果源为空;
从默认(T)的文档:
默认关键字,对于引用types将返回null,对于数值types,则返回零。 对于结构体,它将返回结构体的每个成员初始化为零或空值,这取决于它们是值types还是引用types。 对于可为null的值types,默认返回一个System.Nullable,它被初始化为任何结构。
因此,根据types是引用types还是值types,缺省值可以为null或0,但不能控制缺省行为。
复制了@sloth的评论
而不是YourCollection.FirstOrDefault()
,您可以使用YourCollection.DefaultIfEmpty(YourDefault).First()
例如。
例:
var viewModel = new CustomerDetailsViewModel { MainResidenceAddressSection = (MainResidenceAddressSection)addresses.DefaultIfEmpty(new MainResidenceAddressSection()).FirstOrDefault( o => o is MainResidenceAddressSection), RiskAddressSection = addresses.DefaultIfEmpty(new RiskAddressSection()).FirstOrDefault(o => !(o is MainResidenceAddressSection)), };
你也可以做到这一点
Band[] objects = { new Band { Name = "Iron Maiden" } }; first = objects.Where(o => o.Name == "Slayer") .DefaultIfEmpty(new Band { Name = "Black Sabbath" }) .FirstOrDefault(); // returns "Black Sabbath"
这只使用linq – yipee!
实际上,当我使用集合时,我使用了两种方法来避免NullReferenceException
:
public class Foo { public string Bar{get; set;} } void Main() { var list = new List<Foo>(); //before C# 6.0 string barCSharp5 = list.DefaultIfEmpty(new Foo()).FirstOrDefault().Bar; //C# 6.0 or later var barCSharp6 = list.FirstOrDefault()?.Bar; }
对于C#6.0或更高版本:
使用?.
或?[
在执行成员访问Null-conditional Operators文档之前testing是否为null
示例: var barCSharp6 = list.FirstOrDefault()?.Bar;
C#旧版本:
如果序列为空,则使用DefaultIfEmpty()
检索默认值。 MSDN文档
例如: string barCSharp5 = list.DefaultIfEmpty(new Foo()).FirstOrDefault().Bar;
我只是有类似的情况,并寻找一个解决scheme,使我可以返回一个替代的默认值,而无需照顾在呼叫方每次我需要它。 如果Linq不支持我们想要的,我们通常会做的是编写一个新的扩展来处理它。 这就是我所做的。 这是我想出来的(没有经过testing):
public static class EnumerableExtensions { public static T FirstOrDefault<T>(this IEnumerable<T> items, T defaultValue) { foreach (var item in items) { return item; } return defaultValue; } public static T FirstOrDefault<T>(this IEnumerable<T> items, Func<T, bool> predicate, T defaultValue) { return items.Where(predicate).FirstOrDefault(defaultValue); } public static T LastOrDefault<T>(this IEnumerable<T> items, T defaultValue) { return items.Reverse().FirstOrDefault(defaultValue); } public static T LastOrDefault<T>(this IEnumerable<T> items, Func<T, bool> predicate, T defaultValue) { return items.Where(predicate).LastOrDefault(defaultValue); } }
您可以使用YourCollection.DefaultIfEmpty(YourDefault).First()
来代替YourCollection.FirstOrDefault()
。
使用DefaultIfEmpty()
而不是FirstOrDefault()
。