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()