如何将带判断的LINQ查询改写为单一LINQ表达式?
如何将带条件回退的逻辑改写为单一LINQ表达式?
先明确你的需求:你需要从对象列表中优先筛选包含特定Column(匹配指定Code和Value)的对象,提取其Value;如果没有找到符合优先条件的对象,再回退到筛选所有Column的Code都为空字符串的对象,提取其Value。
原代码逻辑
你的原代码逻辑是清晰的,分开处理了优先匹配和回退场景:
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(); }
你尝试写法的问题
你尝试的写法存在语法逻辑错误:三元运算符的两个分支需要返回相同类型的值,但你在else分支写了v => ...(一个Lambda表达式),而if分支返回的是bool值,这会导致编译失败,而且Where方法需要的是一个返回bool的表达式,你的写法混淆了条件判断和Lambda委托。
正确的单一LINQ表达式写法
这里提供两种简洁的实现方式,都能把逻辑合并为单一LINQ链:
方式1:使用DefaultIfEmpty回退
先获取优先匹配的结果,如果结果为空,则用回退项的结果作为默认值:
var x = values // 优先筛选匹配指定Code和Value的对象 .Where(v => v.Columns.Any(c => c.Code == code && c.Value == value)) .Select(v => v.Value) // 如果优先结果为空,用回退项的结果填充 .DefaultIfEmpty(values .Where(v => v.Columns.All(c => string.IsNullOrEmpty(c.Code))) .Select(v => v.Value) .FirstOrDefault()) .FirstOrDefault();
方式2:通过排序优先匹配项
通过OrderByDescending把符合优先条件的对象排在最前面,其次是符合回退条件的对象,然后直接取第一个结果:
var x = values // 优先把匹配指定Column的对象排前面 .OrderByDescending(v => v.Columns.Any(c => c.Code == code && c.Value == value)) // 然后把回退项(所有Column的Code为空)排前面 .ThenByDescending(v => v.Columns.All(c => string.IsNullOrEmpty(c.Code))) .Select(v => v.Value) .FirstOrDefault();
这两种写法都能实现你需要的逻辑:优先匹配特定Column,不存在则回退到通配项,而且都是单一的LINQ表达式链。
内容的提问来源于stack exchange,提问作者user449689
相关产品推荐
相关产品推荐

