34

I'm learning C#, and I find LINQ absolutely interesting. However what is boggling me is, I can't think of a scenario whereby using LINQ would be an immense help, as its really not that hard replicating LINQ features in code.

Any personal experiences/suggestions you might wanna share?

Thanks!

Taylor Leese
  • 51,004
  • 28
  • 112
  • 141
nubela
  • 1
  • 24
  • 75
  • 123
  • There is a vote to close on grounds of "subjective and argumentative". That's idiotic! This is a simple question about the unique value of Linq. (On the other hand, it is surely a heavily duplicated question on SO so might be closed for that reason.) – Daniel Earwicker Feb 02 '10 at 18:57
  • I'm willing to bet they're "wiki or close" votes. It's subjective so it should probably be a wiki question. – Greg Feb 02 '10 at 19:00
  • Thank you earwicker. I was just curious, I don't understand why people think this is a subjective reason. I didn't know that asking how I might code in a feature be subjective. The community these days. Tsk. – nubela Feb 02 '10 at 19:00
  • 7
    "I'm learning C#, and I find `foreach` absolutely interesting. However what is boggling me is, I can't think of a scenario whereby using `foreach` would be an immense help, as its really not that hard replicating `foreach` features in code." <- question isn't any more helpful than that one. – user7116 Feb 02 '10 at 19:11
  • @sixlettervariables: they both might be syntactic sugar, but `foreach` is single pixie stick whereas LINQ is several gallons of corn syrup. Learning `foreach` took me all of 30 seconds, but I'm still discovering new and interesting things about LINQ, and I don't even use it with databindings. This was a valid question. – FrustratedWithFormsDesigner Feb 02 '10 at 20:32
  • 2
    A Google search reveals such a ridiculous number of results for LINQ, all of which contain a multitude of examples. SO has 90 pages of questions about LINQ. I fail to see how this adds anything to the reams of existing information. Should be closed or a wiki. – user7116 Feb 02 '10 at 20:49
  • Searching with "why use linq" turns up http://stackoverflow.com/questions/339639/why-and-when-to-use-linq and several others like it... – dmckee --- ex-moderator kitten Feb 03 '10 at 05:04
  • Please clarify what you mean by "LINQ". Do you mean LINQ in general, LINQ to SQL, or what? – John Saunders Feb 03 '10 at 17:49
  • You may find Eric Lippert's article of interest: http://blogs.msdn.com/ericlippert/archive/2010/01/11/continuing-to-an-outer-loop.aspx – Brian Feb 03 '10 at 18:30

15 Answers15

20

I find that I'm using LINQ just about any time that I would have previously written a loop to fill a container. I use LINQ to SQL as my ORM and lots of LINQ everywhere else.

Here's a little snippet that I wrote for an Active Directory helper class that finds out if a particular user is an a particular group. Note the use of the Any() method to iterate over the user's authorization groups until it finds one with a matching SID. Much cleaner code than the alternative.

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 );
}

Alternative:

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;
}

or

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;
}

Here's a snippet that does a search against a repository, orders, and converts the first 10 matching business objects into a view-specific model (Distance is the Levenshtein edit distance of the matching model's unique id from the uniqueID parameter).

model.Results = this.Repository.FindGuestByUniqueID( uniqueID, withExpired )
                               .OrderBy( g => g.Distance )
                               .Take( 10 )
                               .ToList()
                               .Select( g => new GuestGridModel( g ) );
Pavel Chikulaev
  • 841
  • 6
  • 12
tvanfosson
  • 524,688
  • 99
  • 697
  • 795
  • 2
    Interesting, elaboration about the loop/filling a container? Some code samples? – nubela Feb 02 '10 at 19:01
  • Strictly speaking this isn't so much using LINQ as it is using the extension methods to which LINQ syntax converts. I just find the fluent style much easier for me to read -- less cognitive dissonance when going back and forth with jQuery. You could certainly represent all of the above using LINQ syntax as well. – tvanfosson Feb 02 '10 at 19:12
  • 1
    Eh, if it's in the System.Linq namespace, I think it counts as using LINQ, regardless of which syntax you call it with. – Joel Mueller Feb 02 '10 at 20:46
  • 1
    why do you keep iterating the users once you found one in your second example? you could just `return true;` – Idan K Feb 03 '10 at 17:54
  • @ldan K - Yes I could simply return true, but I prefer reusing the final exit point in the function. It's just a personal preference (and I'm not always consistent, notice that I do an early return if either the group or user is null). I don't keep iterating, though, notice that I break the loop immediately after setting inGroup to true. I'll provide the alternative, though, which is simpler but still less compact than using LINQ. – tvanfosson Feb 03 '10 at 18:16
16

It depends on what kind of linq you mean.

Is it linq-to-sql? In that case, it's an orm with all the same benefits that come from using any other orm. I don't use it much and can't really say more.

Is it linq-to-objects? In that case, you're really talking about a collection of other things: extension methods, lazy iterators, and a query comprehension syntax. It's an introduction into the world of functional programming. I don't have much use for the query comprehension syntax, but for the rest, I can best demonstrate with an example.

Let's say you want to read a file in line by line. For each line, you want to check if it meets some criteria, convert a portion of those lines to an integer, and sum up the first 10 of those integers that are also within a certain range. Here's the old way you would do that:

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;
}

Here's the new way:

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);
}

Notice the new code is actually shorter. But why is it also better? There are (at least) 4 reasons:

  • Hopefully it's obvious how re-usable the readlines function is. You could factor out more as well, but the point is to show how this style helps you re-use more code.
  • It scales better. Notice all the chained function calls in that last function. You know how many times that code will iterator over the lines in your file? Exactly once! In fact, not even that long as it will stop reading from the file after taking the first 10 items. And if you change it to return an enumerable and then use that elsewhere with other extension methods? Still just once! This lets you build, mix, and re-mix your query results at runtime without costly additional passes on your lists.
  • It's more maintainable. If the criteria changes, it's easy to spot the the exact "rule" (if you will) that you care about and modify just that part.
  • It's more readable. This allows you to express the code in terms of what it is doing rather than how it does it.
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
12

I find LINQ useful when I have a collection of some object and I'm interested in items that meet a certain criteria. Simple example would be searching for all shapes in a collection of shapes that are circles.

var circles =
        from s in allShapes
        where s.Type == ShapeTypes.Circle
        select s;

I admit I could have just written a loop with some code in it, but I find this code shorter and easier to write, and easier to read and understand.

LINQ can also be used with databases, but I actually find I don't do that very much. To each his/her own, I guess.

FrustratedWithFormsDesigner
  • 26,726
  • 31
  • 139
  • 202
11

The book Essential LINQ provides a great one paragraph summary of the benefit of LINQ:

LINQ does more than simply add new features to the language. It introduces a delcarative style of programming into the C# language. The declarative programming model allows developers to craft code that succictly captures their intent, without forcing them to worry about the order in which events take place, or their precise implementation. It allows developers to state what they want to do, rather than how it will be done.

Taylor Leese
  • 51,004
  • 28
  • 112
  • 141
7

You're right, it's rarely very hard to replicate the features in regular C#. It is what they call syntactic sugar. It's just about convenience. You know about automatic properties? The ones that allow you to write public class User { public int Id { get; set; } } That's extremely easy to replicate in "regular" C# code. Even so, automatic properties are still awesome ;)

Filtering and sorting are pretty much the core of LINQ. Consider you have a list of users, called, well, users, and you want to find the ones who have logged in today, and display them in order of most recently logged in. Before LINQ, you'd probably do something like create a new list, that you populate based on the original list, by iterating it, adding what meets the criteria, and then implementing some sort of IComparable. Now you can just do:

users = users.Where(u => u.LastLoggedIn.Date = DateTime.Today)
             .OrderBy(u => u.LastLoggedIn).ToList();

Convenience =)

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
David Hedlund
  • 128,221
  • 31
  • 203
  • 222
4

I use LINQ to DataSet a lot for working with DataTables. DataTables are generic data storages where I often store values e.g. from a loaded CSV file. It is much more readable and comfortable to use LINQ for querying or joining data instead of "brute-force"-ing with for-loops.

galaktor
  • 1,506
  • 14
  • 16
3

I would turn the question around: can you show us how you would emulate Linq features without it? I'm having trouble thinking of a case where it isn't an immense help.

For example, I saw something like this recently:

foreach (var person in people.OrderBy(p => p.Company)
                             .ThenBy(p => p.LastName)
                             .ThenBy(p => p.FirstName)) {
    ...
}

I guess it could have used Arrays.Sort, created a delegate that checked the fields in the right order (backwards from written, right?), and then just lived with the fact that it would only ever work on Arrays. That seems like it would be a lot longer, harder to maintain, and less flexible.

Ken
  • 372
  • 3
  • 9
2

Yes, you can easily use LINQ to Objects using alternative code, and it's not tha difficult. I tend to like the semantics of the lambda expressions, and it does wrap several lines of code into one. But a lot of operations you can do with your own code, except some of the bigger operations (union, intersect, etc.) are easier to do with LINQ.

LINQ has other flavors; LINQ to XML makes it really nice to work with XML data. I really like it better than the previous objects available.

LINQ to SQL and ADO.NET Entity Framework (with LINQ to Entities) are an object relational mapper and can map to your database tables, and act like stored procedures and ADO.NET datasets do, so that is a very nice alternative than weak datasets/datatables, and I like it over strongly typed datasets/tables too.

HTH.

Brian Mains
  • 50,520
  • 35
  • 148
  • 257
  • Upvote because of intersect/union mentions. This is also where I find LINQ to have the most benefit :) Besides that, it often documents intent better than foreach loops. – Merlyn Morgan-Graham Feb 03 '10 at 05:59
2

Have a look at any of the many answers that Jon Skeet provides to Linq questions and you will see how versatile and useful Linq really is.

https://stackoverflow.com/search?q=user:22656+[linq]

Community
  • 1
  • 1
Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
1

Take a look at ReSharper if you haven't already. It has a lot of hints for "... convert to LINQ syntax" so it can usually show you a thing or two you didn't consider when learning. :)

Josh Atkins
  • 223
  • 1
  • 8
1

Somebody mentioned that LINQ is a declarative style of programming. I just wanted to expand on that.

One way I use LINQ is to write test oracle code. It's very important that the test code be simple and as close to "obviously correct" as possible, or else it will end up with as many bugs as the code that it's supposed to test. With one particular feature that I'm testing now, I wrote out a small list of set comprehensions that describe exactly how I expect the feature to work. Thanks to LINQ, converting those comprehensions to code becomes trivially easy:

A = all items
B = [x in A: x.Type = selectedtype, x.Source = "sourceA"]
C = [x in A: x.Source = "sourceB"]
D = B union C

In code:

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);
}

While still quite a bit more verbose than the mathematical expressions, it's much simpler and easier to call "obviously correct" than imperative code would be. The LINQ code is declarative like the math is declarative. Less translation, closer to the spec. LINQ, when used appropriately, is pretty much a "Do what I mean" language.

Note that I wouldn't write the actual code this way. Performance is not a requirement for test code, but it is for the real code, so the real code still needs to be a SQL stored procedure.

JamesH
  • 413
  • 3
  • 8
0

For me, I pretty much only use it to access databases. I almost never query on XML or list's.

Kenny Mann
  • 881
  • 10
  • 28
0

I find it useful to transform/"project" data before binding it to a grid for read-only purposes.

Greg
  • 16,540
  • 9
  • 51
  • 97
0

The LINQ language feature set is not replicable so easily in C# 2.0 code, without extension methods, lambda expressions, and even without the query operators. The whole point of LINQ is that you have some integrated version of queries where you use compiler for sanity checks of them. The other crucial point is the unification of view at different datasources, whether it's a database or in-memory collection. You can live without LINQ, just as you can live without any other feature of the language and code in Assembler, but there are obvious advantages that are hard to oversee ;)

Tomas Vana
  • 18,317
  • 9
  • 53
  • 64
0

One more point to add to all that is a kind of summary point. You can see from above that it's used for convenience and succinctness and can be used with collections, SQL, XML (and anything else that cares to implement a LINQ provider), but best of all you only have to learn the LINQ syntax once and it carries across into all those useful technology areas.

user246091
  • 418
  • 4
  • 14