C# SingleOrDefault 返回 null 时的 LINQ 新实例

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14093594/
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-08-10 10:38:33  来源:igfitidea点击:

LINQ new instance when SingleOrDefault returns null

c#asp.netlinq

提问by r3plica

I have this simple method:

我有这个简单的方法:

    #region Fields

    private Collection<Address> _addresses;

    #endregion

    #region Public methods

    public Address DeliveryAddress()
    {
        if (_addresses == null)
            if (this.Id > 0)
                _addresses = Core.Data.Addresses.GetClient(this.Id);

        return _addresses.SingleOrDefault(x => x.TypeId == AddressType.Delivery);
    }

    public Address InvoiceAddress()
    {
        if (_addresses == null)
            if (this.Id > 0)
                _addresses = Core.Data.Addresses.GetClient(this.Id);

        return _addresses.SingleOrDefault(x => x.TypeId == AddressType.Invoice);
    }

    #endregion

As you can see I trying to return one result for a DeliveryAddressand one result for an InvoiceAddress. My problem is that I would like the link expression to create a new instance of Address()if SingleOrDefaultreturns null. I am really new to linq, so I am not sure whether SingleOrDefaultis the correct expression I should be using.

正如你可以看到我试图返回的一个结果DeliveryAddress,并为一个结果InvoiceAddress。我的问题是我希望链接表达式创建一个新的Address()if SingleOrDefaultreturns实例null。我对 linq 真的很陌生,所以我不确定SingleOrDefault我应该使用的表达式是否正确。

采纳答案by Tim Schmelter

You could use DefaultIfEmptyand use that instance as default value:

您可以使用DefaultIfEmpty该实例作为默认值:

return _addresses.Where(x => x.TypeId == AddressType.Delivery)
                 .DefaultIfEmpty(new Adress())
                 .Single();

回答by Rui Jarimba

Instead of

代替

return _addresses.SingleOrDefault(x => x.TypeId == AddressType.Delivery);

Do something like this:

做这样的事情:

var address = _addresses.SingleOrDefault(x => x.TypeId == AddressType.Delivery);

if(address == null)
    address = new Address();

return address;

回答by Olivier Jacot-Descombes

Use the null-coalescing operator:

使用空合并运算符

return _addresses
    .SingleOrDefault(x => x.TypeId == AddressType.Delivery) ?? new Address();


The expression

表达方式

x ?? y

yields xif xis not null, otherwise y. You can chain the operator

x如果x不是null,则产生,否则产生y。您可以链接运营商

x ?? y ?? z ?? t

This returns the first non-null value or nullif all of them are null.

这将返回第一个非空值,或者null如果它们都是null.



UPDATE

更新

Note that SingleOrDefaultthrows an exception if the sequence has more than one element. If you need the first element of a sequence possibly having no or more than one element, use FirstOrDefaultinstead.

请注意,SingleOrDefault如果序列有多个元素,则抛出异常。如果您需要序列的第一个元素可能没有或多个元素,请FirstOrDefault改用。

回答by Russ Cam

I'd be inclined to write both of these as extension methods on IEnumerable<Address>. You can use the null-coalesing operator to return a new instance if the SingleOrDefault()call returns null.

我倾向于将这两种方法都写成IEnumerable<Address>. 如果SingleOrDefault()调用返回 ,您可以使用空合并运算符返回一个新实例null

public static class AddressExtensions
{
    public static Address DeliveryAddress(this IEnumerable<Address> addresses)
    {
        return addresses.SingleOrDefault(x => x.TypeId == AddressType.Delivery) 
               ?? new Address();
    }

    public static Address InvoiceAddress(this IEnumerable<Address> addresses)
    {
        return addresses.SingleOrDefault(x => x.TypeId == AddressType.Invoice) 
               ?? new Address();
    }
}

回答by KeithS

You could create your own extension method, like this:

您可以创建自己的扩展方法,如下所示:

public static T NewIfNull<T>(this T obj) where T: class, new()
{
   return obj ?? new T();
}

... then tack a usage onto the end of SingleOrDefault:

...然后在 SingleOrDefault 的末尾添加一个用法:

var singleResult = myCollection.SingleOrDefault().NewIfNull();

... or because the logic is so simple, just inline it as other answers have said.

...或者因为逻辑如此简单,就像其他答案所说的那样将其内联。

回答by Tilak

Apart from alternatives in other answers, you can also create your own SingleOrNewExtension method.

除了其他答案中的替代方案,您还可以创建自己的SingleOrNew扩展方法。

public static TSource SingleOrNew<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate ) where T:new()
{
     return source.SingleOrDefault(predicate) ?? new T();
}

It can be used as

它可以用作

return _addresses.SingleOrNew(x => x.TypeId == AddressType.Delivery);