tags:

views:

899

answers:

15

Hi,

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!

+8  A: 

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
+4  A: 

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
Right, agreed. Upvoted.
nubela
A: 

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

Nazadus
+15  A: 

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 group 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 group 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 ) );
tvanfosson
Interesting, elaboration about the loop/filling a container? Some code samples?
nubela
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
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
why do you keep iterating the users once you found one in your second example? you could just `return true;`
Idan K
@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
+2  A: 

Hello,

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
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
A: 

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

Greg
A: 

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

Thomas Wanner
+5  A: 

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 =)

David Hedlund
convenience and readability!
David Hedlund
And why even call .ToList()? 9 times out of 10 it's not needed and it can kill your performance.
Joel Coehoorn
i'll agree with that, but my example assumed a list of users, as per the preceding text. granted, i could easily have changed my example =)
David Hedlund
+9  A: 

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
+2  A: 

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.

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

Robert Harvey
+5  A: 

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
+! Nice example, good reasons
Zyphrax
+3  A: 

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
A: 

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.

A: 

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. :)

Joshua Atkins
+1  A: 

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