Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When should I use LINQ for C#? [closed]

Tags:

c#

.net

linq

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!

like image 647
nubela Avatar asked Feb 02 '10 18:02

nubela


2 Answers

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 ) ); 
like image 132
tvanfosson Avatar answered Oct 14 '22 06:10

tvanfosson


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.
like image 24
Joel Coehoorn Avatar answered Oct 14 '22 07:10

Joel Coehoorn