从内联Linq转换为Linq查询?

时间:2019-01-10 00:26:50

标签: c# linq

我写了一个非常基本的update语句来获取数组中所有重复字母的字符串。这样做的代码很简单,但是我可以看到,对于团队中一些经验不足的开发人员(或不熟悉Linq的开发人员)来说,维护起来很困难。

Linq

我总是可以将其分解为嵌套的string[] results = values.Where(v => v.Where(w => v.Count(c => c == w) > 1).Any()).ToArray(); Console.WriteLine($"There are {results.Length} items with duplicate letters: {string.Join(", ", results)}"); 循环,或以其他几种方式编写:

foreach

但是,我一直想了解有关实际 List<string> results = new List<string>(); foreach (string v in values) { List<char> chars = new List<char>(); foreach (char c in v.ToUpperInvariant()) { if (chars.Contains(c)) { results.Add(v); break; } chars.Add(c); } } Console.WriteLine($"There are {results.Count} items with duplicate letters: {string.Join(", ", results.ToArray())}"); 查询的更多信息,因为它们似乎比内联Linq更具可读性。我更喜欢像在Linq查询中经常看到的那样命名变量:

Linq

我认为,与大多数List<string> myStrings = from val in values ... 代码一样,在保持简洁性的同时,它将更易于维护,但是我无法以嵌套的方式围绕查询查询。我一直尝试将其写为:

Linq

但是我相信它可能更像是:

string[] results = from val in values
                   where from currentCharacter in val
                   where ...

老实说,我也不认为这是实现此目的的正确方法,但这就是为什么我在这里。


如何将嵌套的string[] results = from val in values join currentCharacter in val on ... 语句从内联转换为查询?

2 个答案:

答案 0 :(得分:3)

您可以转换流利的语法代码:

values.Where(v => v.Where(w => v.Count(c => c == w) > 1).Any()).ToArray();

通过查询语法+流利的语法:

var result = (from val in values
              where val.Any(w => val.Count(c => c == w) > 1)
              select val).ToArray();

如您所见,这仍然涉及方法调用,这仅仅是因为某些查询必须表示为方法调用,因为AnyCount没有查询表达式语法(据我所知)。

基本上以一种或另一种方式,您最终将需要在管道中的某处涉及方法调用。


您可能想做的另一件事是将where逻辑提取到某种方法中,例如

bool HasDuplicateCharacters(string input) => input.Any(w => input.Count(c => c == w) > 1);

然后查询将变为:

 var result = (from val in values
               where HasDuplicateCharacters(val)
               select val).ToArray();

与上面的“完全”流利的语法相比,现在阅读此书的任何人都应该知道代码在做什么。

答案 1 :(得分:2)

使用LINQ的好处之一是它专注于意图,不会使读者陷入困境。这对维护很重要:您越早了解它的作用,就越早知道如何进行所需的更改。

使用LINQ语法(from ...)而非流利的(扩展方法)语法也可能有所帮助。例如,在我的答案here中,LINQ语法使查询更易于理解。不管哪种方法都可以。

对于转换嵌套查询,我建议向外进行,因此从内部查询开始,然后首先进行转换。

v.Where(w => v.Count(c => c == w) > 1).Any()

成为:

(from w in v
 where v.Count(c => c == w) > 1
 select w).Any()

然后使用in作为您的外部查询的谓词:

string[] results = (from v in values
                    where (from w in v
                           where v.Count(c => c == w) > 1
                           select w
                          ).Any()
                    select v
                   ).ToArray();

完成该练习后,它看起来仍然有些毛茸茸。其他人建议做一个内部方法,我不会不同意。尽管如此,还是知道如何进行翻译还是很不错的,不仅可以在这种情况下做出充分知情的决定,而且将来也可以对其他查询做出决定。


关于团队的经验,这是一个在学习LINQ的同时向其他人教授LINQ的绝好机会。使用代码审查或午餐非学习课程来讨论技术并互相学习。 “教书是学习两次。”

最后,谈到技术时,“ LINQ”是正确的大小写,而.NET命名约定对众所周知的首字母缩略词使用大小写混合,因此“ Linq”用于诸如名称空间之类的标识符中。 System.Linq