我正在学习C#,我发现LINQ非常有趣。然而令我难以置信的是,我无法想到使用LINQ会给你带来巨大帮助的场景,因为它在代码中复制LINQ功能并不是那么难。
您可能想分享的任何个人经历/建议?
谢谢!
答案 0 :(得分:18)
我发现我几乎在任何时候都会使用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
是来自uniqueID的匹配模型的唯一ID的Levenshtein编辑距离参数)。
model.Results = this.Repository.FindGuestByUniqueID( uniqueID, withExpired )
.OrderBy( g => g.Distance )
.Take( 10 )
.ToList()
.Select( g => new GuestGridModel( g ) );
答案 1 :(得分:15)
这取决于你的意思是什么样的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;
}
以下是新方式:
IEnumerable<string> ReadLines(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个理由:
答案 2 :(得分:12)
当我收集某个对象并且我对符合某个条件的项目感兴趣时,我发现LINQ很有用。简单的例子是搜索圆形形状集合中的所有形状。
var circles =
from s in allShapes
where s.Type == ShapeTypes.Circle
select s;
我承认我可以写一个包含一些代码的循环,但我觉得这段代码更简单,更易于编写,更易于阅读和理解。
LINQ也可以用于数据库,但实际上我发现我不那么做。对于他/她自己,我猜。
答案 3 :(得分:10)
本书Essential LINQ提供了LINQ的好处的一个很好的段落摘要:
LINQ不仅仅是添加新内容 语言的功能。它 介绍了一种演绎风格 编程到C#语言。该 声明性编程模型允许 开发人员制作代码 succictly捕获他们的意图, 没有强迫他们担心 事件的发生顺序, 或者他们的确切实施。它 允许开发人员陈述他们的意思 想要做,而不是如何 完成。
答案 4 :(得分:6)
你是对的,在常规C#中复制这些功能很少很难。这就是他们所说的语法糖。这只是为了方便。你知道自动属性吗?允许你编写public class User { public int Id { get; set; } }
的那些极其易于在“常规”C#代码中复制。即便如此,自动属性仍然很棒;)
过滤和排序几乎是LINQ的核心。假设您有一个用户列表,名为users
,您希望找到今天登录的用户,并按照最近登录的顺序显示它们。在LINQ之前,您可能会做类似于创建一个新列表,您根据原始列表填充,迭代它,添加符合条件的内容,然后实现某种IComparable
。现在你可以这样做:
users = users.Where(u => u.LastLoggedIn.Date = DateTime.Today)
.OrderBy(u => u.LastLoggedIn).ToList();
便利性=)
答案 5 :(得分:4)
我使用LINQ to DataSet来处理DataTables。 DataTables是通用数据存储,我经常存储值,例如从加载的CSV文件。使用LINQ查询或连接数据而不是使用for循环进行“暴力破解”更加可读和舒适。
答案 6 :(得分:3)
我会回答这个问题:你能告诉我们如何在没有它的情况下模仿Linq功能吗?我很难想到不是一个巨大帮助的案例。
例如,我最近看到过这样的事情:
foreach (var person in people.OrderBy(p => p.Company)
.ThenBy(p => p.LastName)
.ThenBy(p => p.FirstName)) {
...
}
我想它本来可以使用Arrays.Sort
,创建了一个以正确的顺序检查字段的委托(从写入向后,对吧?),然后只是生活在它只能在数组上工作的事实。这似乎会更长,更难维护,也不那么灵活。
答案 7 :(得分:2)
是的,您可以使用替代代码轻松使用LINQ to Objects,并不难。我倾向于喜欢lambda表达式的语义,它确实将几行代码包装成一行。但是你可以使用自己的代码执行很多操作,除了一些较大的操作(并集,交叉等),使用LINQ更容易。
LINQ还有其他风味; LINQ to XML使得处理XML数据变得非常好。我真的比以前的对象更喜欢它。
LINQ to SQL和ADO.NET实体框架(使用LINQ to Entities)是一个对象关系映射器,可以映射到数据库表,并像存储过程和ADO.NET数据集一样,这是一个非常好的选择比弱数据集/数据表,我喜欢强类型数据集/表格。
HTH。
答案 8 :(得分:2)
看看Jon Skeet为Linq问题提供的众多答案中的任何一个,你会看到Linq的多功能性和实用性。
答案 9 :(得分:1)
如果您还没有,请查看ReSharper。它有很多关于“...转换为LINQ语法”的提示,因此它通常可以向您显示学习时未考虑的一两件事。 :)
答案 10 :(得分:1)
有人提到LINQ是一种声明式的编程风格。我只想扩展它。
我使用LINQ的一种方法是编写测试oracle代码。测试代码很简单并且尽可能接近“明显正确”非常重要,否则最终会出现与它应该测试的代码一样多的错误。通过我现在正在测试的一个特定功能,我写了一小部分集合理解,这些理解准确地描述了我期望该功能如何工作。感谢LINQ,将这些理解转换为代码变得非常简单:
A = all items
B = [x in A: x.Type = selectedtype, x.Source = "sourceA"]
C = [x in A: x.Source = "sourceB"]
D = B union C
在代码中:
IEnumerable<MyClass> SetB(IEnumerable<MyClass> allItems, MyType type)
{
var result = from item in allItems
where item.Type == type && item.Source == "sourceA"
select item;
return result;
}
IEnumerable<MyClass> SetC(IEnumerable<MyClass> allItems)
{
var result = from item in allItems
where item.Source == "sourceB"
select item;
return result;
}
IEnumerable<MyClass> SetD(IEnumerable<MyClass> allItems, MyType type)
{
var setB = SetB(allItems, type);
var setC = SetC(allItems);
return setB.Union(setC);
}
虽然比数学表达式还要冗长得多,但它比命令式代码更简单,更容易称为“明显正确”。 LINQ代码是声明性的,就像数学是声明性的一样。减少翻译,更接近规范。 LINQ,如果使用得当,几乎就是“我的意思”语言。
请注意,我不会以这种方式编写实际代码。性能不是测试代码的要求,但它适用于实际代码,因此实际代码仍然需要是SQL存储过程。
答案 11 :(得分:0)
对我来说,我几乎只用它来访问数据库。我几乎从不查询XML或列表。
答案 12 :(得分:0)
我认为在将数据绑定到网格之前转换/“项目”数据是有用的,只是为了只读目的。
答案 13 :(得分:0)
LINQ语言功能集在C#2.0代码中不易复制,没有扩展方法,lambda表达式,甚至没有查询运算符。 LINQ的重点在于您有一些集成版本的查询,您可以使用编译器对它们进行完整性检查。另一个关键点是不同数据源的视图统一,无论是数据库还是内存中的集合。你可以在没有LINQ的情况下生活,就像在Assembler中没有语言和代码的任何其他功能一样,但是有明显的优点很难监督;)
答案 14 :(得分:0)
还有一点要添加到所有这是一个总结点。您可以从上面看到它用于方便和简洁,可以用于集合,SQL,XML(以及任何其他关心实现LINQ提供程序的东西),但最重要的是,您只需要学习一次LINQ语法贯穿所有有用的技术领域。