14

我有这个简单的方法:

    #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

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

4

6 回答 6

29

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

return _addresses.Where(x => x.TypeId == AddressType.Delivery)
                 .DefaultIfEmpty(new Adress())
                 .Single();
于 2012-12-30T18:58:43.133 回答
13

使用空合并运算符

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

表达方式

x ?? y

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

x ?? y ?? z ?? t

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


更新

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

于 2012-12-30T18:59:33.723 回答
3

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

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

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

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

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

于 2012-12-30T19:01:07.497 回答
1

代替

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;
于 2012-12-30T18:58:24.813 回答
0

我倾向于将这两种方法都写为IEnumerable<Address>. SingleOrDefault()如果调用返回,您可以使用 null-coalesing 运算符返回一个新实例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();
    }
}
于 2012-12-30T19:00:34.870 回答
0

除了其他答案中的替代方法外,您还可以创建自己的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);
于 2012-12-30T19:16:36.920 回答