在单个LINQ表达式中转换if

时间:2018-05-18 12:15:41

标签: c# linq

我正在努力在单个LINQ表达式中转换这段代码。

var x = values
    .Where(v => v.Columns.Any(c => c.Code == code && c.Value == value))
    .Select(v => v.Value)
    .FirstOrDefault();

if (x == null)
{
    x = values
        .Where(v => v.Columns.All(c => string.IsNullOrEmpty(c.Code))
        .Select(v => v.Value)
        .FirstOrDefault();

}

基本上我有一个对象列表。每个对象都包含Column个对象和Value的列表。

我想过滤包含特定Column对象的对象(基于CodeValue),但如果这个组合不存在,我想回到包含Column个对象列表的实体,其Code等于string.Empty(外卡)。

我尝试了以下不同的方法,但没有成功:

var x = values
    .Where(v => v.Columns.Any(c => c.Code == code && c.Value == value)
        ? v.Columns.Any(c => c.Code == code && c.Value == value)
        : v => v.Columns.All(c => string.IsNullOrEmpty(c.Code))
    .Select(v => v.Value)
    .FirstOrDefault();

2 个答案:

答案 0 :(得分:3)

我建议Concat两种选择:

var x = values
    .Where(v => v.Columns.Any(c => c.Code == code && c.Value == value))
    .Select(v => v.Value)
    .Concat(values // second alternative if 1st returns empty cursor
       .Where(v => v.Columns.All(c => string.IsNullOrEmpty(c.Code))
       .Select(v => v.Value))
    .FirstOrDefault();

修改:您可以通过将.Select(v => v.Value)提取到

来简化查询(请参阅CSharpie的评论)
var x = values
    .Where(v => v.Columns.Any(c => c.Code == code && c.Value == value))
    .Concat(values // second alternative if 1st returns empty cursor
       .Where(v => v.Columns.All(c => string.IsNullOrEmpty(c.Code)))
    .Select(v => v.Value) 
    .FirstOrDefault();

答案 1 :(得分:1)

您可以使用DefaultIfEmpty(fallback)

var fallBackValue =  values
    .Where(v =>  v.Columns.All(c => string.IsNullOrEmpty(c.Code))
    .Select(v => v.Value)
    .FirstOrDefault();

var x = values
    .Where(v => v.Columns.Any(c => c.Code == code && c.Value == value))
    .Select(v => v.Value)
    .DefaultIfEmpty(fallBackValue)
    .First(); // FirstOrDefault not nessesary anymore;

这样做的好处是,您甚至可以在不破坏逻辑的情况下选择多个,因此如果Take(3)(例如)不会返回任何项目,则仍会返回后备值。

它也很有效,因为后备值将独立于主查询计算,并且可以从属性返回,因此它只需要初始化一次。

另一个(类似选项)是空合并运算符(如果Value是引用类型):

var x = values
    .Where(v => v.Columns.Any(c => c.Code == code && c.Value == value))
    .Select(v => v.Value)
    .FirstOrDefault() ?? fallBackValue; 

但我更喜欢第一种,因为它可以被链接并且也很容易修改(即Take(x))。