Blogs

Paul Kimmel's Blog

How LINQ is Like a For Loop

     

One of the best ways for me to understand something (relatively) new is to figure out how its like something else, the role it plays as something new, and how to use it. Language INtegrated Query (or LINQ) is a relatively new thing. Let’s step back and look at some existing code that is a ubiquitous staple (see Listing 1).

Listing 1:  A basic for-loop that copies a desired subset of items from collection to another.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CompareLinqToForLoop
{
  class Program
  {
    static void Main(string[] args)
    {
      int[] integers = {1,2,3,4,5,6,7,8,9};

      List<int> results = new List<int>();
      for (int k = 0; k < integers.Length; i++)
        if (integers[k] % 2 == 0)
          results.Add(integers[k]);

      Array.ForEach(results.ToArray(), r => Console.WriteLine(r));
      Console.ReadLine(); 
    }
  }
}

The code is trivial but it demonstrates a basic use of a for-loop. The code starts with an array of integers. A new target object, the generic List is created to receive the desired subset. The for-loop iterates over the source collection of integers, tests each element—and in this case the even integers—and places them in the target List. In a general sense the for loop iterates over items and performs an operation on them. In this specific example the operation is to copy selected items to a new subset, the generic List.

LINQ performs a very similar role to the for loop and subset generator. Instead of specifically creating the target object, defining the for loop, and a separate test, LINQ supports all of these operations in an integrated way. I don’t mean to downplay the value of LINQ or oversimplify it, but if you use this knowledge as a basic starting point—for loop, subset collection generator—then LINQ is pretty approachable. Using LINQ the code in Listing 1 can be re-written as follows (see Listing 2):

Listing 2: Selecting a subset of objects using LINQ.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CompareLinqToForLoop
{
  class Program
  {
    static void Main(string[] args)
    {
      int[] integers = {1,2,3,4,5,6,7,8,9};

      var results = from i in integers
                   where i % 2 == 0
                   select i;

      Array.ForEach(results.ToArray(), r => Console.WriteLine(r));
      Console.ReadLine(); 
    }
  }
}

The from clause is the equivalent of the for-loop. The value right after the from keyword is called the range value. The range value plays the same role as the iterator variable in the for-loop. The range variable is i in Listing 2. The value after the in keyword is the source collection. The where clause plays the role of the test. In Listing 1 an if-conditional is used; in Listing 2 the where clause plays the same role. The where clause in LINQ works and looks like a SQL where clause. Finally, the select clause performs the role of copying the desired target objects. The term often associated with the select clause is projection. The term projection is used when you apply the new keyword in the select clause to define a new type. In the example the select clause is simply accumulating the integers that pass the test in the where clause.

The result of the LINQ query is an IEnumerable<T> object where T in the example is an integer. The result of the LINQ query plays the role of the instantiated List<T> in Listing 1. The var keyword is used to support an unknown, or anonymous, type. You can define the return type on the left side of the equal, but you don’t have to. The reason you want to use var besides that it requires less typing is because LINQ let’s you project a new, as yet undefined, anonymous type.

Anonymous types is where LINQ starts to become really powerful. Suppose you have a class of employee objects and you want a subset of those employee objects, containing just the employee name and phone number, a contact list. Historically, you would have the Employee class, define a new class containing the name and number fields, and then use a for loop to move the data from the source Employee collection to a collection of instances of the new type. With LINQ you don’t have to define the new type—containing name and number. You can define the new type in the select statement with the new keyword, and simply specify just the values for the projected new type. At its essence LINQ is like a for loop. However, because you can define new types in the select clause on the fly you can avoid defining all of those extra classes that are used for lookups, reports, or to answer user queries.

If you are just getting started with LINQ, think: from is a for-loop, where is the test, and select is the operation performed for each iteration of the loop. If you need a new type don’t define the class explicitly define it in the select clause. (For more information on LINQ you can check out my book LINQ Unleashed for C# or look at some of the LINQ examples in my upcoming book Professional DevExpress ASP.NET Controls. (The DevExpress doesn’t emphasize LINQ, but there are some LINQ examples.)

Published Oct 07 2009, 08:43 PM by Paul Kimmel (DevExpress)
Bookmark and Share

Comments

 

Johnny K said:

some :-) characters apear as Lamps or smiles in the examples.

despite the fact i allready personally know those i would like to see dev express team to use more vb.net samples .

October 7, 2009 5:28 PM
 

Paul Kimmel (DevExpress) said:

Johnny K. wrote that he wanted to see more VB examples.. Fair enough. The next few blog posts do I will mix in some VB and then try to alternate between VB and C#.

October 7, 2009 9:28 PM
 

Aaron said:

If you are going to use one language or another, I suggest you do the samples in both... VB.Net Linq does not always equal C# Linq. Especially when you mix in lambda expressions. Plus, VB.Net Linq does not handle null values in the data like C# does, so you may need more code in VB.Net than you do in C#.

October 8, 2009 9:58 AM
 

Crono said:

Thanks Paul for showing us the light! ;)

October 8, 2009 10:01 AM
 

Minor Bolanos said:

Paul.

Do you have any comment about Linq limitations?.

Everyone write about Linq pros but never write about cons. I know that you want to sell your books. I think that is important to say all the truth about Linq.

1. Referencial integrity on memory like Dataset. foreign key constraint, Default values, Allow nulls (required), etc.

2. Rejected Changes to recover deleted record on memory (DataTable RejectChages Method).

3. batch-update and batch-delete performance. One SQL sentence per row.

4. Linq ORM can't create relationship between views like dataset.

5. Microsoft is killing Linq to SQL to replace it with Linq to Entity Framework.

I do not talk about extensions or workaround to fix all those limitations.

I think that Linq is only a good tools for Query.

It is a Language Integrated Query and that's it.

October 8, 2009 10:04 AM
 

Paul Kimmel (DevExpress) said:

Minor: Sometimes I write about limitations of a product, but not as much lately. And, by the way, I haven't heard anything about LINQ to SQL being killed. That is probably an unfounded rumor.

October 8, 2009 11:05 AM
 

Minor Bolanos said:

Paul

You have any comment about my point 1, 2, 3, 4.

If very important for me to know a different view about that limitations.

Do you know if Microsoft is planing to fix all those limitations in future version?.

I read about point 5 on this link:

www.infoq.com/.../DLINQ-Future

October 8, 2009 12:36 PM
 

Aaron said:

Minor,

Linq to SQL is far from dead. Here is a list of changes coming in 4.0

damieng.com/.../linq-to-sql-changes-in-net-40

As far as points 1 - 3, I have never had an issue with any of these. For point number 2, just use GetOriginalEntityState or deep copy the original entity yourself.

For number 4, we don't use views...

October 8, 2009 3:51 PM
 

Paul Kimmel (DevExpress) said:

Thanks for weighing in Aaron. I didn't have my catlog of shortcomings handy. I look at any sub-framework this way: I use it when it works; I don't mind mixing technologies because they are all classes whether you use ADO straight, LINQ to SQL, or XPO, and if one technology falls short in one particular area use something else. I used to like to use one homogeneous approach for an entire application, but that can be too limiting.

October 9, 2009 10:58 AM
 

Minor Bolanos said:

Aaron,

Linq is an ideal technology for Web Applications (WebForms) but not for Win Application (WinForm).

In Web Applications (AspxGridView) you edit one record at the time. In Win Applications (XtraGrid) you edit many record at the time.

1. Referential integrity on memory like Dataset. Foreign key constraint, Default values, Allow nulls (required), etc.

Linq only check the integrity of your data when you Summit your data on your Database. Dataset (ADO.NET) checks the integrity when you update your data on memory and when you update your data on your Database.

THIS A BIG LIMITATION BECAUSE YOU NEED TO MAKE A CONNECTION TO THE DATABASE TO CHECK THE INTEGRITY OF YOUR DATA.

2. Rejected Changes to recover deleted record on memory (DataTable RejectChages Method).

If you  use GetOriginalEntityState or deep copy the original entity yourself. THIS IS A WORK AROUND, NOT A NATURAL BEHAVIOR.

REMEMBER GOOD PRACTICE FOR GOOD AND PROFESSIONAL PROGRAMMER: KEEP YOUR CODE SIMPLE.

3. batch-update and batch-delete performance. One SQL sentence per row.

Everyone knows that A BIG BIG BIG limitation in LINQ. Please Google: batch update in linq and research a little.

4. Linq ORM can't create relationship between views like dataset.

When you said "we don't use views". With that sentence I know that you do not have any knowledge or experience in Transact-SQL.

For big applications, with millions of records to increase performance VIEW are very important. You need to learn more about partitioned view, index view, using view for security, etc.

And if you use view with linq you save code.

AGAIN GOOD PRACTICE FOR GOOD AND PROFESSIONAL PROGRAMMER: KEEP YOUR CODE SIMPLE.

5. Microsoft is killing Linq to SQL to replace it with Linq to Entity Framework.

www.infoq.com/.../DLINQ-Future

Paul,

Do you have any answer for point 1 to 4 or you agree with me about all those limitations.

Thanks

October 12, 2009 9:40 AM
 

Minor Bolanos said:

Aaron,

If you read your own link:

damieng.com/.../linq-to-sql-changes-in-net-40

Pingback ThinqLinq - LINQ to SQL enhancements for 2010 on June 2nd, 2009

[...] one of the people on the LINQ to SQL team, just posted a list of 40+ changes that are coming for LINQ to SQL for .Net 4.0. Looking through the list, most of the items are bug fix items and not feature [...]

October 12, 2009 10:33 AM
 

James Smith said:

I agree with Minor 100%

October 13, 2009 12:09 PM
More from DevExpress
Live Chat
Have a pre-sales question?
Need assistance with your evaluation?
We are here to help.
Chat is one of the many ways you can contact members of the DevExpress Team. We are available Monday-Friday between 8:30am and 5:00pm Pacific Time.
If you need additional product information, require pre-sales assistance, or want help with your order, write to us at info@devexpress.com or call us at
+1 (818) 844-3383.