Using LINQ

Posted on - Last Modified on

LINQ is the abbreviation of Language Integrated Queries introduced in .NET Framework 3.5, and it's still available. It offers a concise, strongly typed interface that can access a lot of data sources, like objects, collections, XML files, DataSets, Entities.

Along with LINQ, the .NET Framework 3.5 introduced a couple of new features, which help to use LINQ efficiently. Here's a list.

Anonymous Types and Implicit Typing

This feature was added so you can rapidly group any kind of data together without having to create a new, specific type. The compiler will create the type at compile time and will generate a name for it:

     var myAnonymousTypeExample = new
            {
                Name = "John Doe",
                Birthdate = DateTime.Today,
                PhoneNumber = "132113213545",
                Websites = new List<string>
                {
                    "http://johndoe.com",
                    "http://john.doe",
                    "https://doejohn.example.com"
                }
            };

The usage of the var keyword is necessary because the type of the right hand site object is not defined by the developer. It is an anonymous type, and will be named by the compiler at compile time.

If I try to access a field which was not added to the object at creation, then I get an error message where the type is already named (thanks to Visual Studio’s Intellisense):

anonymouse type

Extension Methods

The possibility to create extension methods was added so developers can extend the existing functionality of classes that cannot be derived or accessed (maybe because these are defined in another assembly that can't be changed due to system dependencies). Extension methods have to be defined using a static class and should always be static. The first argument of these methods has to be the this keyword and the type that it extends. 

public static class StringExtensions
    {
        public static int HowManyVowels(this string text)
        {
            int nrOfVowels = 0;

            if (!string.IsNullOrWhiteSpace(text))
            {
                List<char> vowels = new List<char> { 'a','e','i','o','u'};
                for (int i = 0; i < text.Length; i++)
                {
                    if (vowels.Contains(text[i]))
                    {
                        nrOfVowels++;
                    }
                }
            }

            return nrOfVowels;
        }
    }

A sample application that uses the above extension method:

static void Main(string[] args)
{
      string testText = "The quick brown fox jumps over the lazy dog.";
      Console.WriteLine("The text '{0}' has {1} vowels.", testText, testText.HowManyVowels());

      Console.ReadLine();
}

The screenshot below shows the output when the application is executed:

Extension Methods

Lambda Expressions

The Lambda operator (=>) is used when you need to pass a strongly typed delegate as an argument to a method. This simplifies the creation of delegates.

var numbers = Enumerable.Range(1, 100).ToList();

var oddNumbers = numbers.Where((number) => number % 2 != 0);

The Where() extension method defined for the generic List<T> requires a function argument, in this case I added a lambda expression - (number) => number % 2 != 0 - which filters the numbers and returns only the odd numbers from the numbers collection.

Using LINQ

In order to use LINQ, there are a couple of assemblies needed to be referenced in your project. These are System.Core.dll, System.Data.DataSetExtensions.dll and System.Data.Xml.dll. The System.Core.dll is the single assembly that is always needed.

LINQ looks very similar to standard SQL syntax, but you cannot match it to SQL or rewrite it to SQL without detailed analysis.

The same example for odd numbers can be rewritten using LINQ as:

var oddNumbers2 = from nr in numbers
                  where nr % 2 != 0
                  select nr;

I was using var, which helped define the implicit type of oddNumbers2 variable (IEnumerable<int>). There are a lot of utility extension methods defined for the IEnumerable interface like:

     var sum = oddNumbers2.Sum();
            var smallerThanTwenty = oddNumbers2.TakeWhile((number) => number < 20);
            var reveresedOddNumbers = oddNumbers2.Reverse();
            var maxOddNumber = oddNumbers2.Max();
            var minOddNumber = oddNumbers2.Min();
            var intersectedOddNumbers = oddNumbers2.Intersect(
                    new List<int>{ 2,3,4,5,6,7,8,9 }
                ); // the result will be 3,5,7,9 

The name of these methods are self-explanatory. Sum() adds all the items in the list and returns the result. The TakeWhile() method will take the values in oddNumbers2, while the predicate evaluates to true for the members. The Reverse() method reverses the list of oddNumbers2. Max() and Min() returns the maximum and minimum value from the list of items. The Intersect() method selects only the common parts within both lists and returns only those (the same concept as the intersection of sets).

I only used basic types from the .NET Framework, but you can use custom objects too. I have created a Dog and a Size class, I use these in further examples:

    public class Size
    {
        public int Height { get; set; }
        public int Length { get; set; }
    }

    public class Dog
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public Size Size { get; set; }
        public int Weight { get; set; }

    }

Let’s suppose there is a kennels list of dogs which was loaded from some database and is stored in a collection of type List<Dog>:

var kennels = new List<Dog>()
            {
                new Dog(){
                    Name = "Blake",
                    Age = 2,
                    Weight = 22,
                    Size = new Size() { Height = 56, Length = 75 }
                },
                new Dog(){
                    Name = "Snoopy",
                    Age = 7,
                    Weight = 8,
                    Size = new Size() { Height = 16, Length = 25 }
                },
                new Dog(){
                    Name = "Booch",
                    Age = 4,
                    Weight = 35,
                    Size = new Size() { Height = 68, Length = 89 }
                }
            };

            var dogsOlderThan2years = from dog in kennels
                                      where dog.Age > 2
                                      select dog;

            var dogsBiggerThan50 = from dog in kennels
                                   where dog.Size.Height > 50 || dog.Size.Length > 50
                                   select dog.Name;

In the first example I select all the dogs which are older than 2 years. Note that I selected the whole dog object.

In the second example I selected all the dog names where the dog’s size is bigger than 50. Of course both of these LINQs could have been implemented using a for or a foreach statement and some helper arrays, but using LINQ results in a nicer and more elegant solution that is readable.

Deferred Execution

LINQs are not executed until you iterate over the result collection. It's intended to be implemented this way, because engineers wanted to have the correct result even if the collection which the LINQ was defined for has changed. Here's an example:

var numbers = Enumerable.Range(1, 10).ToList();
            var oddNumbers = numbers.Where((number) => number % 2 != 0);
            foreach (var item in oddNumbers)
            {
                Console.WriteLine(item);
            }

            numbers.Add(105);
            numbers.Add(107);

            Console.WriteLine("----------------");
            
            foreach (var item in oddNumbers)
            {
                Console.WriteLine(item);
            }

After the first foreach is executed, the following numbers will be written to console: 1,3,5,7,9. When the second foreach is executed, the output will be: 1,3,5,7,9,105,107. As you can see the LINQ expression is re-evaluated and the result may change.

If you want to immediately execute the LINQ queries you can do this by invoking one of the extension methods: ToArray<T>(), ToList<T>(),ToDictionary<T,V>(). 

Posted 13 April, 2015

Greg Bogdan

Software Engineer, Blogger, Tech Enthusiast

I am a Software Engineer with over 7 years of experience in different domains(ERP, Financial Products and Alerting Systems). My main expertise is .NET, Java, Python and JavaScript. I like technical writing and have good experience in creating tutorials and how to technical articles. I am passionate about technology and I love what I do and I always intend to 100% fulfill the project which I am ...

Next Article

Catch PR Expert Conrad Egusa on WAMA, Live!