.net FirstOrDefault:除 null 以外的默认值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12972295/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 16:40:27  来源:igfitidea点击:

FirstOrDefault: Default value other than null

.netlinq

提问by Sachin Kainth

As I understand it, in Linq the method FirstOrDefault()can return a Defaultvalue of something other than null. What I haven't worked out is what kind of things other than null can be returned by this (and similar) method when there are no items in the query result. Is there any particular way that this can be set up so that if there is no value for a particular query some predefined value is returned as the default value?

据我了解,在 Linq 中,该方法FirstOrDefault()可以返回Defaultnull 以外的值。我还没有弄清楚的是,当查询结果中没有项目时,这个(和类似的)方法可以返回除 null 之外的哪些类型的东西。有没有什么特别的方法可以设置它,以便如果特定查询没有值,则某些预定义值将作为默认值返回?

采纳答案by Rawling

General case, not just for value 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);

Again, this can't really tell if there wasanything in your sequence, or if the first value was the default.

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

If you care about this, you could do something like

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

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

and use as

并用作

var result = query.FirstOr(otherDefaultValue);

although as Mr. Steak points out this could be done just as well by .DefaultIfEmpty(...).First().

尽管正如 Steak 先生指出的那样,这也可以通过.DefaultIfEmpty(...).First().

回答by Jon Skeet

As I understand it, in Linq the method FirstOrDefault() can return a Default value of something other than null.

据我了解,在 Linq 中,方法 FirstOrDefault() 可以返回非空值的默认值。

No. Or rather, it alwaysreturns the default value for the element type... which is either a null reference, the null value of a nullable value type, or the natural "all zeroes" value for a non-nullable value type.

不。或者更确切地说,它总是返回元素类型的默认值......它要么是空引用,要么是可空值类型的空值,要么是不可空值类型的自然“全零”值。

Is there any particular way that this can be set up so that if there is no value for a particular query some predefined value is returned as the default value?

有没有什么特别的方法可以设置它,以便如果特定查询没有值,则某些预定义值将作为默认值返回?

For reference types, you can just use:

对于引用类型,您可以使用:

var result = query.FirstOrDefault() ?? otherDefaultValue;

Of course this will alsogive you the "other default value" if the first value is present, but is a null reference...

这当然给你“等默认值”如果第一个值存在,但为空引用...

回答by Vitamin C

You can use DefaultIfEmptyfollowed by First:

您可以使用DefaultIfEmpty后跟First

T customDefault = ...;
IEnumerable<T> mySequence = ...;
mySequence.DefaultIfEmpty(customDefault).First();

回答by RB.

From the documentation for FirstOrDefault

来自FirstOrDefault的文档

[Returns] default(TSource) if source is empty;

[返回] default(TSource) 如果源为空;

From the documentation for default(T):

来自default(T)的文档:

the default keyword, which will return null for reference types and zero for numeric value types. For structs, it will return each member of the struct initialized to zero or null depending on whether they are value or reference types. For nullable value types, default returns a System.Nullable, which is initialized like any struct.

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

Therefore, the default value can be null or 0 depending on whether the type is a reference or value type, but you cannot control the default behaviour.

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

回答by Matas Vaitkevicius

Copied over from comment by @sloth

复制自@sloth 的评论

Instead of YourCollection.FirstOrDefault(), you could use YourCollection.DefaultIfEmpty(YourDefault).First()for example.

代替YourCollection.FirstOrDefault(),您可以使用YourCollection.DefaultIfEmpty(YourDefault).First()例如。

Example:

例子:

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)),
    };

回答by BurnWithLife

You can also do this

你也可以这样做

    Band[] objects = { new Band { Name = "Iron Maiden" } };
    first = objects.Where(o => o.Name == "Slayer")
        .DefaultIfEmpty(new Band { Name = "Black Sabbath" })
        .FirstOrDefault();   // returns "Black Sabbath" 

This uses only linq - yipee!

这仅使用 linq - yipee!

回答by Samuel Diogo

Actually, I use two approaches to avoid NullReferenceExceptionwhen I'm working with collections:

实际上,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;
}

For C# 6.0 or later:

对于 C# 6.0 或更高版本:

Use ?.or ?[to test if is null before perform a member access Null-conditional Operators documentation

在执行成员访问之前使用?.?[测试是否为 null空条件运算符文档

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

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

C# older version:

C# 旧版本:

Use DefaultIfEmpty()to retrieve a default value if the sequence is empty.MSDN Documentation

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

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

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

回答by harri

I just had a similar situation and was looking for a solution that allows me to return an alternative default value without taking care of it at the caller side every time I need it. What we usually do in case Linq does not support what we want, is to write a new extension that takes care of it. That′s what I did. Here is what I came up with (not tested though):

我刚刚遇到了类似的情况,并且正在寻找一种解决方案,该解决方案允许我在每次需要时返回替代默认值而无需在调用方处理它。如果 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);
    }
}

回答by Aaron Gibson

I know its been a while but Ill add to this, based on the most popular answer but with a little extension Id like to share the below:

我知道它已经有一段时间了,但我会根据最受欢迎的答案补充一点,但有一点扩展 Id 想分享以下内容:

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

This allows me to call it inline as such with my own example I was having issues with:

这使我可以在我自己的示例中将其内联称为我遇到的问题:

_controlDataResolvers.FirstOr(x => x.AppliesTo(item.Key), () => newDefaultResolver()).GetDataAsync(conn, item.ToList())

So for me I just wanted a default resolver to be used inline, I can do my usual check and then pass in a function so a class isn't instantiated even if unused, its a function to execute when required instead!

所以对我来说,我只想内联使用默认解析器,我可以做我通常的检查,然后传入一个函数,这样即使未使用类也不会实例化,而是在需要时执行它的函数!

回答by Raj.A

Instead of YourCollection.FirstOrDefault(), you could use YourCollection.DefaultIfEmpty(YourDefault).First()for example.

代替YourCollection.FirstOrDefault(),您可以使用YourCollection.DefaultIfEmpty(YourDefault).First()例如。