据我了解,在Linq中,该方法FirstOrDefault()
可以返回Default
非null值。我还没有解决的是,当查询结果中没有项目时,此(和类似方法)可以返回null以外的其他东西。有什么特殊的方法可以设置它,以便在没有特定查询的值的情况下,返回一些预定义值作为默认值?
MyCollection.Last().GetValueOrDefault(0)
那样。否则,下面的@Jon Skeet答案是IMO正确的。
据我了解,在Linq中,该方法FirstOrDefault()
可以返回Default
非null值。我还没有解决的是,当查询结果中没有项目时,此(和类似方法)可以返回null以外的其他东西。有什么特殊的方法可以设置它,以便在没有特定查询的值的情况下,返回一些预定义值作为默认值?
MyCollection.Last().GetValueOrDefault(0)
那样。否则,下面的@Jon Skeet答案是IMO正确的。
Answers:
一般情况,不仅限于值类型:
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);
尽管正如Steak先生指出的那样,这也可以做到.DefaultIfEmpty(...).First()
。
<T>
使用它们的名称,但是更严重的是,value == default(T)
它不起作用(因为谁知道是否T
可以将其等同进行比较?)
EqualityComparer<T>.Default.Equals(value, default(T))
用于避免装箱并避免异常(如果值是null
据我了解,在Linq中,方法FirstOrDefault()可以返回默认值,而不是null。
否。或者,它总是返回元素类型的默认值...它可以是空引用,可为空的值类型的空值,或为非可为空的值类型的自然“全零”值。
有什么特殊的方法可以设置它,以便在没有特定查询的值的情况下,返回一些预定义值作为默认值?
对于引用类型,您可以使用:
var result = query.FirstOrDefault() ?? otherDefaultValue;
这当然也给你“等默认值”如果第一个值存在,但为空引用...
int
。我更喜欢使用DefaultIfEmpty
:src.Where(filter).DefaultIfEmpty(defaultValue).First()
。适用于值类型和引用类型。
从FirstOrDefault的文档中
[返回] default(TSource)如果source为空;
从default(T)的文档中:
默认关键字,对于引用类型,它将返回null;对于数值类型,它将返回零。对于结构,它将返回初始化为零或null的结构的每个成员,具体取决于它们是值类型还是引用类型。对于可为空的值类型,默认返回System.Nullable,该系统将像任何结构一样进行初始化。
因此,根据类型是引用类型还是值类型,默认值可以为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)),
};
DefaultIfEmpty
如果集合为空(具有0个项目),则返回默认值。如果First
在示例中使用WITH匹配表达式,并且该条件找不到任何项目,则返回值为空。
您也可以这样做
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!
FirstOrDefault
而不是First
。根据msdn.microsoft.com/zh-cn/library/bb340482.aspx,建议的用法是First
实际上,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文档
例:
var barCSharp6 = list.FirstOrDefault()?.Bar;
使用DefaultIfEmpty()
如果序列是空检索默认值。MSDN文档
例:
string barCSharp5 = list.DefaultIfEmpty(new Foo()).FirstOrDefault().Bar;
YourCollection.FirstOrDefault()
可以使用代替,YourCollection.DefaultIfEmpty(YourDefault).First()
例如。
我刚刚遇到过类似的情况,并且正在寻找一种解决方案,该解决方案使我可以返回备用默认值,而不必在每次需要时都在调用方使用它。如果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);
}
}
我知道已经有一段时间了,但根据最流行的答案,我会加一句:我想分享以下内容:
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())
因此,对我来说,我只是希望将默认的解析程序用于内联,我可以进行常规检查,然后传入一个函数,这样即使未使用该类也不会实例化,而是可以在需要时执行该函数!
使用DefaultIfEmpty()
代替FirstOrDefault()
。
YourCollection.FirstOrDefault()
可以使用代替,YourCollection.DefaultIfEmpty(YourDefault).First()
例如。