原文在此优化
原linq语句:this
var res = employees .Where(e => e.Gender == "Male") .Take(3) .Where(e => e.Salary > avgSalary) .OrderBy(e => e.Age);
扩展方法:spa
public static IEnumerable<T> LogLINQ<T>(this IEnumerable<T> enumerable, string logName, Func<T, string> printMethod) { #if DEBUG int count = 0; foreach (var item in enumerable) { if (printMethod != null) { Debug.WriteLine($"{logName}|item {count} = {printMethod(item)}"); } count++; yield return item; } Debug.WriteLine($"{logName}|count = {count}"); #else return enumerable; #endif }
使用方法调试
var res = employees .LogLINQ("source", e => e.Name) .Where(e => e.Gender == "Male") .LogLINQ("logWhere", e => e.Name) .Take(3) .LogLINQ("logTake", e => e.Name) .Where(e => e.Salary > avgSalary) .LogLINQ("logWhere2", e => e.Name) .OrderBy(e => e.Age);
说明和解释:日志
在LINQ查询中的每一个操做以后放置 LogLINQ
方法。它能够选择打印经过此操做的全部项目和总数。code
logName
是每一个输出的前缀,能够轻松查看编写它的查询步骤。我喜欢将其命名为以后操做相同的名称。blog
Fun<T,string>printMethod
容许打印给定项目的任何内容。在上面的示例中,我选择使用 e=>e.Name
打印员工的姓名,当为 null
时,除总数外,不会打印任何内容。get
为了优化,此方法尽在调试模式下有效( #if DEBUG
)。在发布模式下,它什么都不作。string
每一个项目都按顺序打印,无需等待操做结束,这是由于LINQ的 lazy
特性。如下是查看单个操做结果的提示:将整个输出复制到 notepad++
。而后使用Ctrl+Shift+F(Find)并查找日志前缀(例如 logWhere2
)。在查找对话框,点击Find All in Current Document。这将仅显示与日志名称前缀匹配的行。it