如何调试LINQ结果

时间:2012-07-11 20:26:04

标签: c# linq debugging linq-to-objects

我是linq的新手。所以有时候只是不明白linq是如何工作的。所以在VS2010 IDE中有任何工具或内置机制来详细调试linq执行。假设我有这个linq查询

var to_search = new[] { "Geo", "JCB" };

var result = from sr in list
             let w = to_search.FirstOrDefault(ts => sr.Title.ToLower().Contains(ts.ToLower()))
             where w != null
             let a = new {sr=sr, word=w.ToLower()}
             group a by a.word into g
             orderby g.Count() descending
             let sorted = g.OrderByDescending(a=> a.sr.Title.Select((c, i) => a.sr.Title.Substring(i)).Count(sub => sub.ToLower().StartsWith(a.word)))
             from a in sorted 
             select a.sr;

var completeList = result.Concat(list.Except(result));

如何详细调试上面的linq查询。请指导我。感谢。

3 个答案:

答案 0 :(得分:6)

为了回应这个看似简单的问题,可以写出很多内容!事实上,我已在Simple-Talk.com上的文章LINQ Secrets Revealed: Chaining and Debugging中详细撰写。以下是其要点摘要:

  • 您可以使用调试器进入某些LINQ查询,但这取决于查询中表达式和语句的组成(因为您只能进入语句)。
  • LINQ方法链的工作原理是一个基本规则:每个非终端方法都将IEnumerable<T>作为输入,并返回IEnumerable<T>作为输出。
  • 只要符合该基本规则,您就可以注入“无操作”声明,为您提供“踏脚石”。也就是说,意识到你总是可以将.Select(z => z)置于一个没有后果的方法链中,使用它的变体,即:z => { return z; }
  • 您可以类似地注入诊断方法来提供输出,而不仅仅是提供潜在的断点。 LINQPad,不仅仅是LINQ而且是C#的优秀暂存器,以其强大的Dump()方法为幌子提供了这一功能。转储是一个对象可视化工具,可以提供复杂数据结构的惊人可视化。
  • 根据Bart De Smet在其内容丰富的文章LINQ to Objects – Debugging中的工作,您可以将简化的Dump风格带回Visual Studio中 - 我提供了附在我上面提到的文章中的代码。< / LI>
  • 感谢Robert Ivanc在LINQPad Visualizer上的工作,您甚至可以将LINQPad可视化工具引入Visual Studio(尽管您需要手动为单个表达式启动它;您无法将其连接到Dump()方法)。

作为一个简短的例子,请考虑这个简单的方法链:

string[] Words = new string[]
{"   KOOKABURRA", "Frogmouth", "kingfisher   ", "loon", "merganser"};

Words
        .Select(word => word.Trim())
        .Select(word => word.ToLower())
        .Where(word => word.StartsWith("k"))
        .OrderBy(word => word);

在Visual Studio项目中包含Dump扩展方法之后,您可以像这样最小化它...

Words
    .Select(word => word.Trim())
    .Dump()
    .Select(word => word.ToLower())
    .Dump()
    .Where(word => word.StartsWith("k"))
    .Dump()
    .OrderBy(word => word)
    .Dump();

......或者更精心地像这样......

Words
    .Dump(w => "ORIGINAL: " + w, ConsoleColor.Yellow)
    .Select(word => word.Trim())
    .Dump(w => "TRIMMED: " + w, ConsoleColor.Yellow)
    .Select(word => word.ToLower())
    .Dump(w => "LOWERCASE: " + w, ConsoleColor.Green)
    .Where(word => word.StartsWith("k"))
    .Dump(w => "FILTERED to 'K': " + w, ConsoleColor.Red)
    .OrderBy(word => word)
    .Dump(w => "SORTED: " + w, ConsoleColor.Blue);

...将输出分别呈现为图的左侧或右侧: Diagnostic output from Dump method in Visual Studio

作为预告片,我会说虽然这确实很有用,但您必须看到LINQPad可以使用相同输出执行的增强可视化(为了您的方便,here再次链接)。

答案 1 :(得分:1)

我的方法是在查询中插入断点,或使用名为LINQPad的工具。 http://www.linqpad.net/

答案 2 :(得分:0)

我相信你应该像往常一样在任何其他代码中放置断点。我不是100%肯定,因为我经常将LINQ语法编写为匹配的扩展方法。

但是,这是另一种选择,您可以使用扩展方法重写查询并在每个方法上添加断点。

但如果有疑问,请使用F11:)

此外,LINQPad应该能够在这里提供帮助。