繁体   English   中英

SingleOrDefault 返回 null 时的 LINQ 新实例

[英]LINQ new instance when SingleOrDefault returns null

我有这个简单的方法:

    #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

如您所见,我尝试为DeliveryAddress返回一个结果,为InvoiceAddress返回一个结果。 我的问题是,如果SingleOrDefault返回null ,我希望链接表达式创建一个Address()的新实例。 我对 linq 真的很SingleOrDefault ,所以我不确定SingleOrDefault是否是我应该使用的正确表达式。

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

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

使用空合并运算符

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

表达方式

x ?? y

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

x ?? y ?? z ?? t

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


更新

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

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

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

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

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

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

代替

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

做这样的事情:

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

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

return address;

我倾向于将这两个都写为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();
    }
}

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

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

它可以用作

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

暂无
暂无

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

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