我什么时候应该使用LINQ for C#?

时间:2010-02-02 18:53:58

标签: c# .net linq

我正在学习C#,我发现LINQ非常有趣。然而令我难以置信的是,我无法想到使用LINQ会给你带来巨大帮助的场景,因为它在代码中复制LINQ功能并不是那么难。

您可能想分享的任何个人经历/建议?

谢谢!

15 个答案:

答案 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个理由:

  • 希望显而易见的是readlines功能的可重用性。您也可以考虑更多因素,但关键是要说明这种风格如何帮助您重复使用更多代码。
  • 它更好地扩展。注意最后一个函数中的所有链式函数调用。您知道该代码将对文件中的行进行迭代次数吗? 恰好一次!事实上,即使只是在服用前10项后它将停止从文件中读取。如果你改变它以返回一个枚举,然后在其他地方使用其他扩展方法? 仍然只是一次!这使您可以在运行时构建,混合和重新混合查询结果,而无需在列表上进行昂贵的额外传递。
  • 它更易于维护。如果标准发生变化,很容易发现您关心的确切“规则”(如果愿意)并仅修改该部分。
  • 它更具可读性。这允许您根据其执行的内容而不是如何执行代码来表达代码。

答案 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的多功能性和实用性。

https://stackoverflow.com/search?q=user:22656+[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语法贯穿所有有用的技术领域。