我正在努力在单个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
对象的对象(基于Code
和Value
),但如果这个组合不存在,我想回到包含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();
答案 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)
提取到
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)
)。