我正在学习C#,我发现LINQ非常有趣.然而令我难以置信的是,我无法想到使用LINQ会给你带来巨大帮助的场景,因为它在代码中并不是那么难以复制LINQ功能.
您可能想分享的任何个人经历/建议?
谢谢!
我发现我几乎在任何时候使用LINQ,我之前已经编写了一个循环来填充容器.我使用LINQ to SQL作为我的ORM,并在其他地方使用大量LINQ.
这是我为Active Directory帮助程序类编写的一个小片段,用于查明特定用户是否是特定组.请注意使用Any()方法迭代用户的授权组,直到找到具有匹配SID的授权组.比替代品更清晰的代码.
private bool IsInGroup( GroupPrincipal group, UserPrincipal user ) { if (group == null || group.Sid == null) { return false; } return user.GetAuthorizationGroups() .Any( g => g.Sid != null && g.Sid.CompareTo( group.Sid ) == 0 ); }
替代方案:
private bool IsInGroup( GroupPrincipal group, UserPrincipal user ) { if (group == null || group.Sid == null) { return false; } bool inGroup = false; foreach (var g in user.GetAuthorizationGroups()) { if ( g => g.Sid != null && g.Sid.CompareTo( group.Sid ) == 0 ) { inGroup = true; break; } } return inGroup; }
要么
private bool IsInGroup( GroupPrincipal group, UserPrincipal user ) { if (group == null || group.Sid == null) { return false; } foreach (var g in user.GetAuthorizationGroups()) { if ( g => g.Sid != null && g.Sid.CompareTo( group.Sid ) == 0 ) { return true; } } return false; }
这是一个片段,用于搜索存储库,订单,并将前10个匹配的业务对象转换为特定于视图的模型(Distance
是唯一ID参数中匹配模型的唯一ID的Levenshtein编辑距离).
model.Results = this.Repository.FindGuestByUniqueID( uniqueID, withExpired ) .OrderBy( g => g.Distance ) .Take( 10 ) .ToList() .Select( g => new GuestGridModel( g ) );
这取决于你的意思是什么样的linq.
它是linq-to-sql吗?在这种情况下,它是一个具有使用任何其他orm所带来的所有相同好处的orm.我不太用它,也不能说更多.
是linq-to-objects?在这种情况下,你真的在谈论其他东西的集合:扩展方法,惰性迭代器和查询理解语法.它是对函数式编程世界的介绍.我没有太多使用查询理解语法,但对于其余部分,我最好用一个例子来演示.
假设您想逐行读取文件.对于每一行,您要检查它是否符合某些条件,将这些行的一部分转换为整数,并总结那些也在某个范围内的前10个整数.这是你将要做的旧方法:
int SumXValues(string filename) { string line; int sum = 0; int count = 0; using (var rdr = new StreamReader(filename)) { while ( (line = rdr.ReadLine()) != null && count < 10) { int val; if (int.TryParse(line.Substring(3,3)) { if (val > 4 && val < 25) { sum += val; count ++; } } } } return sum; }
这是新的方式:
IEnumerableReadLines(string filename) { string line; using (var rdr = new StreamReader(filename)) while ( (line = rdr.ReadLine()) != null) yield return line; } int SumXValues(string filename) { return ReadLines(filename) .Select(l => l.Substring(3,3)) .Where(l => int.TryParse(l)) .Select(i => int.Parse(i)) .Where(i => i > 4 && i < 16) .Take(10) .Sum(i => i); }
请注意,新代码实际上更短.但为什么它也更好? 有(至少)4个理由:
希望显而易见的是readlines功能的可重用性.您也可以考虑更多,但重点是展示这种风格如何帮助您重用更多代码.
它扩展得更好.注意最后一个函数中的所有链式函数调用.您知道该代码将对文件中的行进行迭代次数吗? 完全一次! 事实上,即使只是在服用前10项后它将停止从文件中读取.如果你改变它以返回一个枚举,然后在其他地方使用其他扩展方法? 还是只有一次! 这使您可以在运行时构建,混合和重新混合查询结果,而无需在列表上进行昂贵的额外传递.
它更易于维护.如果标准发生变化,很容易发现您关心的确切"规则"(如果愿意)并仅修改该部分.
它更具可读性.这允许您根据其执行的内容而不是如何执行来表达代码.
当我有一些对象的集合并且我对符合某个标准的项目感兴趣时,我发现LINQ很有用.简单的例子是搜索圆形形状集合中的所有形状.
var circles = from s in allShapes where s.Type == ShapeTypes.Circle select s;
我承认我可能只是编写了一个包含一些代码的循环,但我发现这段代码更简单,更易于编写,更易于阅读和理解.
LINQ也可以用于数据库,但实际上我发现我不那么做.我想,对于他/她自己.
Essential LINQ这本书提供了LINQ优点的一个很好的段落摘要:
LINQ不仅仅是为语言添加新功能.它为C#语言引入了一种编程风格的编程.声明性编程模型允许开发人员制作完全捕获其意图的代码,而不必强迫他们担心事件发生的顺序或其精确实现.它允许开发人员说明他们想要做什么,而不是如何做.
你是对的,在常规C#中复制这些功能很少很难.这就是他们所说的语法糖.这只是为了方便.你知道自动属性吗?允许你编写的public class User { public int Id { get; set; } }
那些非常容易在"常规"C#代码中复制.即便如此,自动属性仍然很棒;)
过滤和排序几乎是LINQ的核心.考虑一下你有一个用户列表,好了,users
你想找到今天登录的用户,并按照最近登录的顺序显示它们.在LINQ之前,你可能会做一些像创建一个新用户的事情. list,您根据原始列表填充,迭代它,添加符合条件的内容,然后实现某种类型IComparable
.现在你可以这样做:
users = users.Where(u => u.LastLoggedIn.Date = DateTime.Today) .OrderBy(u => u.LastLoggedIn).ToList();
方便=)