简体   繁体   English

SingleOrDefault 返回 null 时的 LINQ 新实例

[英]LINQ new instance when SingleOrDefault returns null

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 DeliveryAddress and one result for an InvoiceAddress .如您所见,我尝试为DeliveryAddress返回一个结果,为InvoiceAddress返回一个结果。 My problem is that I would like the link expression to create a new instance of Address() if SingleOrDefault returns null .我的问题是,如果SingleOrDefault返回null ,我希望链接表达式创建一个Address()的新实例。 I am really new to linq, so I am not sure whether SingleOrDefault is the correct expression I should be using.我对 linq 真的很SingleOrDefault ,所以我不确定SingleOrDefault是否是我应该使用的正确表达式。

You could use DefaultIfEmpty and use that instance as default value:您可以使用DefaultIfEmpty并将该实例用作默认值:

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

Use the null-coalescing operator :使用空合并运算符

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

The expression表达方式

x ?? y

yields x if x is not null , otherwise y .如果x不为null ,则产生x ,否则产生y You can chain the operator您可以链接运营商

x ?? y ?? z ?? t

This returns the first non-null value or null if all of them are null .这将返回第一个非 null 值或null如果它们都是null


UPDATE更新

Note that SingleOrDefault throws an exception if the sequence has more than one element.请注意,如果序列具有多个元素,则SingleOrDefault会引发异常。 If you need the first element of a sequence possibly having no or more than one element, use FirstOrDefault instead.如果您需要序列的第一个元素可能没有或多个元素,请改用FirstOrDefault

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. ...或者因为逻辑如此简单,就像其他答案所说的那样将其内联。

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;

I'd be inclined to write both of these as extension methods on IEnumerable<Address> .我倾向于将这两个都写为IEnumerable<Address>上的扩展方法。 You can use the null-coalesing operator to return a new instance if the SingleOrDefault() call returns null .如果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();
    }
}

Apart from alternatives in other answers, you can also create your own SingleOrNew Extension 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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM