据我了解,在Linq中,方法FirstOrDefault()
可以返回除{null}以外的值的Default
值。我没有解决的是当查询结果中没有项目时,此(和类似)方法可以返回除null之外的其他类型的东西。是否有任何特定的方法可以设置它,以便如果没有特定查询的值,一些预定义的值将作为默认值返回?
答案 0 :(得分:172)
据我了解,在Linq中,方法FirstOrDefault()可以返回除null之外的默认值。
没有。或者更确切地说,总是返回元素类型的默认值...它是空引用,可空值类型的空值,或非自然的“全零”值-nullable值类型。
是否有任何特定的方法可以设置它,以便如果没有特定查询的值,某些预定义的值将作为默认值返回?
对于参考类型,您只需使用:
var result = query.FirstOrDefault() ?? otherDefaultValue;
当然,如果第一个值存在,还会给你“其他默认值”,但是它是一个空引用...
答案 1 :(得分:55)
您可以使用DefaultIfEmpty,然后使用First:
T customDefault = ...;
IEnumerable<T> mySequence = ...;
mySequence.DefaultIfEmpty(customDefault).First();
答案 2 :(得分:39)
一般情况,不仅仅是价值类型:
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);
虽然正如牛先生指出的那样,.DefaultIfEmpty(...).First()
可以做到这一点。
答案 3 :(得分:18)
[返回]默认值(TSource),如果source为空;
来自default(T)的文档:
default关键字,对于引用类型将返回null,对于数值类型将返回零。对于结构体,它将返回初始化为struct或null的结构的每个成员,具体取决于它们是值还是引用类型。对于可空值类型,default返回一个System.Nullable,它像任何struct一样初始化。
因此,默认值可以为null或0,具体取决于类型是引用类型还是值类型,但您无法控制默认行为。
答案 4 :(得分:6)
复制@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)),
};
答案 5 :(得分:5)
你也可以这样做
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!
答案 6 :(得分:4)
实际上,当我使用集合时,我使用两种方法来避免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;
}
在执行成员访问Null-conditional Operators documentation
之前,使用?.
或?[
来测试是否为null
实施例:
var barCSharp6 = list.FirstOrDefault()?.Bar;
如果序列为空,请使用DefaultIfEmpty()
检索默认值。MSDN Documentation
实施例:
string barCSharp5 = list.DefaultIfEmpty(new Foo()).FirstOrDefault().Bar;
答案 7 :(得分:1)
我只是遇到了类似的情况,并且正在寻找一种解决方案,它允许我在每次需要时都不会在呼叫方处返回其他默认值。如果Linq不支持我们想要的东西,我们通常会做的是编写一个新的扩展来处理它。就是我做的。这是我想出的(虽未测试):
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);
}
}
答案 8 :(得分:0)
而不是YourCollection.FirstOrDefault()
,您可以使用YourCollection.DefaultIfEmpty(YourDefault).First()
作为示例。
答案 9 :(得分:0)
我知道已经有一段时间了,但根据最流行的答案,我会加一句,但我想分享一下以下内容:
static class ExtensionsThatWillAppearOnIEnumerables
{
public static T FirstOr<T>(this IEnumerable<T> source, Func<T, bool> predicate, Func<T> alternate)
{
var thing = source.FirstOrDefault(predicate);
if (thing != null)
return thing;
return alternate();
}
}
这使我可以像在遇到问题的我自己的示例中那样直接内联调用:
_controlDataResolvers.FirstOr(x => x.AppliesTo(item.Key), () => newDefaultResolver()).GetDataAsync(conn, item.ToList())
所以对我来说,我只想将默认解析器用于内联,我可以进行常规检查,然后传入一个函数,这样即使未使用该类也不会实例化,而是可以在需要时执行该函数! / p>
答案 10 :(得分:0)
如果项目列表不是可空类型,请考虑将其强制转换为可空类型,然后使用您想要的默认值 firstordefault 和 null 合并运算符。
示例:
static class MyClass
{
public enum Level { Low, Medium, High }
public static void Dosomething()
{
var levels = Enum.GetValues<Level>();
var myLevel = levels.Select(x => (Level?)x).FirstOrDefault() ?? Level.Medium; // The Default value other than null
}
}
答案 11 :(得分:0)
这对我们有用
int valueOrDefault = myList.Find(x => x.Id == 1)?.Value ?? -1;
答案 12 :(得分:-2)
使用DefaultIfEmpty()
代替FirstOrDefault()
。