FirstOrDefault:除null之外的默认值

Sac*_*nth 130 .net linq

据我所知,在Linq中,该方法FirstOrDefault()可以返回Defaultnull以外的值.我没有解决的是当查询结果中没有项目时,此(和类似)方法可以返回除null之外的其他类型的东西.是否有任何特定的方法可以设置,以便如果没有特定查询的值,一些预定义的值将作为默认值返回?

Jon*_*eet 189

据我所知,在Linq中,方法FirstOrDefault()可以返回除null之外的默认值.

不.或者更确切地说,它总是返回元素类型的默认值...它可以是空引用,可空值类型的空值,也可以是非可空值类型的自然"全零"值.

是否有任何特定的方法可以设置,以便如果没有特定查询的值,一些预定义的值将作为默认值返回?

对于参考类型,您可以使用:

var result = query.FirstOrDefault() ?? otherDefaultValue;
Run Code Online (Sandbox Code Playgroud)

当然,如果第一个值存在,这将为您提供"其他默认值",但是它是一个空引用...

  • 比我接受的答案更适合我! (12认同)
  • 我知道这个问题要求引用类型,但是当元素是像“int”这样的值类型时,您的解决方案不起作用。我更喜欢使用“DefaultIfEmpty”:“src.Where(filter).DefaultIfEmpty(defaultValue).First()”。适用于值类型和引用类型。 (8认同)

小智 60

您可以使用DefaultIfEmpty,然后使用First:

T customDefault = ...;
IEnumerable<T> mySequence = ...;
mySequence.DefaultIfEmpty(customDefault).First();
Run Code Online (Sandbox Code Playgroud)


Raw*_*ing 41

一般情况,不仅仅是价值类型:

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);
Run Code Online (Sandbox Code Playgroud)

再次,这真的不能告诉如果在你的序列任何东西,或者如果第一个值是默认的.

如果你关心这个,你可以做类似的事情

static class ExtensionsThatWillAppearOnIEnumerables
{
    public static T FirstOr<T>(this IEnumerable<T> source, T alternate)
    {
        foreach(T t in source)
            return t;
        return alternate;
    }
}
Run Code Online (Sandbox Code Playgroud)

并用作

var result = query.FirstOr(otherDefaultValue);
Run Code Online (Sandbox Code Playgroud)

虽然正如牛先生指出的那样,这也可以做到.DefaultIfEmpty(...).First().

  • @Rawling使用`EqualityComparer &lt;T&gt; .Default.Equals(value,default(T))`避免装箱,并且如果value为null则避免异常。 (2认同)

RB.*_*RB. 19

来自FirstOrDefault的文档

如果source为空,则返回默认值(TSource);

默认文档(T):

default关键字,它将为引用类型返回null,为数值类型返回零.对于结构体,它将返回初始化为struct或null的结构的每个成员,具体取决于它们是值还是引用类型.对于可空值类型,default返回一个System.Nullable,它像任何结构一样初始化.

因此,默认值可以为null或0,具体取决于类型是引用还是值类型,但您无法控制默认行为.


小智 9

.NET6/c#10 解决方案

.NET6 / c#10 通过向 *OrDefault LINQ 方法添加新功能来解决此问题。新的重载允许您指定在序列为空时要使用的默认值。

public static TSource FirstOrDefault<TSource> (this System.Collections.Generic.IEnumerable<TSource> source, Func<TSource,bool> predicate, TSource defaultValue);
Run Code Online (Sandbox Code Playgroud)

返回序列中满足条件的第一个元素,如果未找到此类元素,则返回指定的默认值。

这是一个例子;

var nums = new List<int> { 1, 2, 3 };
var target = 4;

var value = nums.FirstOrDefault(x => x == target, -1); // value becomes -1.
Run Code Online (Sandbox Code Playgroud)

来源: https: //learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.firstordefault ?view=net-6.0#System_Linq_Enumerable_FirstOrDefault__1_System_Collections_Generic_IEnumerable___0____0 _


Mat*_*ius 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)),
    };
Run Code Online (Sandbox Code Playgroud)

  • 请注意,`DefaultIfEmpty`返回默认的IF集合为空(有0项).如果您在示例中使用匹配表达式的"First",并且该条件未找到任何项目,则返回值将为空. (2认同)

Bur*_*ife 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" 
Run Code Online (Sandbox Code Playgroud)

这仅使用linq-yipee!

  • 这个答案和维生素C答案之间的唯一区别是,这个答案使用的是“ FirstOrDefault”而不是“ First”。根据https://msdn.microsoft.com/zh-cn/library/bb340482.aspx,建议的用法是“第一”。 (2认同)

Sam*_*ogo 5

实际上,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;
}
Run Code Online (Sandbox Code Playgroud)

对于C#6.0或更高版本:

在执行成员访问之前,使用?.?[测试是否为空Null-conditional Operators文档

例: var barCSharp6 = list.FirstOrDefault()?.Bar;

C#较旧的版本:

使用DefaultIfEmpty()如果序列是空检索默认值。MSDN文档

例: string barCSharp5 = list.DefaultIfEmpty(new Foo()).FirstOrDefault().Bar;