CODEDIGEST
Home » Articles
Search
 

Technologies
 

Sponsored links
 

CodeDigest Navigation
 

Technology News
No News Feeds available at this time.
 

Community News
No News Feeds available at this time.
 
LINQ to Objects in C#

By N. Satheesh Kumar
Posted On Mar 19,2009
Article Rating:
Average Rating: 1
No of Ratings: 1
No of Comments: 5
Category: C#
Print this article.

LINQ to Objects in C#

 

LINQ to Objects means that we can use LINQ to query objects in a collection. We can access the in-memory data structures using LINQ. We can query any type of object that implements the IEnumerable interface or IEnumerable, which is of generic type. Lists, arrays, and dictionaries are some collection objects that can be queried using LINQ.

In this article, author N. Satheesh Kumar shows us how to query different objects using LINQ operators and avoid having to use the looping method to filter the values in a collection.

Without LINQ, we would have to go through the values one-by-one and then find the required details. However, using LINQ we can directly query collections and filter the required values without using any looping. LINQ provides powerful filtering, ordering, and grouping capabilities that requires minimum coding. For example, if we want to find out the types stored in an assembly and then filter the required details, we can use LINQ to query the assembly details using System.Reflection classes. The System.Reflection namespace contains types that retrieve information about assemblies, modules, members, parameters, and other entities as collections are managed code, by examining their metadata. Also, files under a directory are a collection of objects that can be queried using LINQ. We shall see some of the examples for querying some collections.

Array of Integers

The following example shows an integer array that contains a set of integers. We can apply the LINQ queries on the array to fetch the required values.

    int[] integers = { 1, 6, 2, 27, 10, 33, 12, 8, 14, 5 };
       IEnumerable<int> twoDigits =
       from numbers in integers
       where numbers >= 10
       select numbers;
       Console.WriteLine("Integers > 10:");
       foreach (var number in twoDigits)
       {
          Console.WriteLine(number);
       }

 

The integers variable contains an array of integers with different values. The variable twoDigits, which is of type IEnumerable, holds the query. To get the actual result, the query has to be executed.

The actual query execution happens when the query variable is iterated through the foreach loop by calling GetEnumerator() to enumerate the result. Any variable of type IEnumerable<T>, can be enumerated using the foreach construct. Types that support IEnumerable<T> or a derived interface such as the generic IQueryable<T>, are called queryable types. All collections such as list, dictionary and other classes are queryable. There are some non-generic IEnumerable collections like ArrayList that can also be queried using LINQ. For that, we have to explicitly declare the type of the range variable to the specific type of the objects in the collection, as it is explained in the examples later in this article.

The twoDigits variable will hold the query to fetch the values that are greater than or equal to 10. This is used for fetching the numbers one-by-one from the array. The foreach loop will execute the query and then loop through the values retrieved from the integer array, and write it to the console. This is an easy way of getting the required values from the collection.

If we want only the first four values from a collection, we can apply the Take() query operator on the collection object. Following is an example which takes the  first four integers from the collection. The four integers in the resultant collection are displayed using the foreach method.

   IEnumerable<int> firstFourNumbers = integers.Take(4);
   Console.WriteLine("First 4 numbers:");
   foreach (var num in firstFourNumbers)
   {
      Console.WriteLine(num);
   }

 

The opposite of Take() operator is Skip() operator, which is used to skip the number of items in the collection and retrieve the rest. The following example skips the first four items in the list and retrieves the remaining.

   IEnumerable<int> skipFirstFourNumbers = integers.Skip(4);
   Console.WriteLine("Skip first 4 numbers:");
   foreach (var num in skipFirstFourNumbers)
   {
      Console.WriteLine(num);
   }

 

This example shows the way to take or skip the specified number of items from the collection. So what if we want to skip or take the items until we find a match in the list? We have operators to get this. They are TakeWhile() and SkipWhile().

For example, the following code shows how to get the list of numbers from the integers collection until 50 is found. TakeWhile() uses an expression to include the elements in the collection as long as the condition is true and it ignores the other elements in the list. This expression represents the condition to test the elements in the collection for the match.

   int[] integers = { 1, 9, 5, 3, 7, 2, 11, 23, 50, 41, 6, 8 };
   IEnmerable<int> takeWhileNumber = integers.TakeWhile(num =>
      num.CompareTo(50) != 0);
   Console.WriteLine("Take while number equals 50");
   foreach (int num in takeWhileNumber)
      {
         Console.WriteLine(num.ToString());
      }

 

Similarly, we can skip the items in the collection using SkipWhile(). It uses an expression to bypass the elements in the collection as long as the condition is true. This expression is used to evaluate the condition for each element in the list. The output of the expression is boolean. If the expression returns false, the remaining elements in the collections are returned and the expression will not be executed for the other elements. The first occurrence of the return value as false will stop the expression for the other elements and returns the remaining elements. These operators will provide better results if used against ordered lists as the expression is ignored for the other elements once the first match is found.

   IEnumerable<int> skipWhileNumber = integers.SkipWhile(num =>
      num.CompareTo(50) != 0);
   Console.WriteLine("Skip while number equals 50");
   foreach (int num in skipWhileNumber)
   {
      Console.WriteLine(num.ToString());
   }

 

Collection of Objects

In this section we will see how we can query a custom built objects collection. Let us take the Icecream object, and build the collection, then we can query the collection. This Icecream class in the following code contains different properties such as Name, Ingredients, TotalFat, and Cholesterol.

    public class Icecream
    {
        public string Name { get; set; }
        public string Ingredients { get; set; }
        public string TotalFat { get; set; }
        public string Cholesterol { get; set; }
        public string TotalCarbohydrates { get; set; }
        public string Protein { get; set; }
        public double Price { get; set; }
    }

 

Now build the Icecreams list collection using the class defined perviously.

    List<Icecream> icecreamsList = new List<Icecream>
        {
            new Icecream {Name="Chocolate Fudge Icecream", Ingredients="cream,
                milk, mono and diglycerides...", Cholesterol="50mg",
                Protein="4g", TotalCarbohydrates="35g", TotalFat="20g",
                Price=10.5
        },
        new Icecream {Name="Vanilla Icecream", Ingredients="vanilla extract,
            guar gum, cream...", Cholesterol="65mg", Protein="4g",
            TotalCarbohydrates="26g", TotalFat="16g", Price=9.80 },
            new Icecream {Name="Banana Split Icecream", Ingredients="Banana, guar
            gum, cream...", Cholesterol="58mg", Protein="6g",
            TotalCarbohydrates
="24g", TotalFat="13g", Price=7.5 }
        };

 

We have icecreamsList collection which contains three objects with values of the Icecream type. Now let us say we have to retrieve all the ice-creams that cost less. We can use a looping method, where we have to look at the price value of each object in the list one-by-one and then retrieve the objects that have less value for the Price property. Using LINQ, we can avoid looping through all the objects and its properties to find the required ones. We can use LINQ queries to find this out easily. Following is a query that fetches the ice-creams with low prices from the collection. The query uses the where condition, to do this. This is similar to relational database queries. The query gets executed when the variable of type IEnumerable is enumerated when referred to in the foreach loop.

    List<Icecream> Icecreams = CreateIcecreamsList();
    IEnumerable<Icecream> IcecreamsWithLessPrice =
    from ice in Icecreams
    where ice.Price < 10
    select ice;
    Console.WriteLine("Ice Creams with price less than 10:");
    foreach (Icecream ice in IcecreamsWithLessPrice)
    {
        Console.WriteLine("{0} is {1}", ice.Name, ice.Price);
    }

 

As we used List<Icecream> objects, we can also use ArrayList to hold the objects, and a LINQ query can be used to retrieve the specific objects from the collection according to our need. For example, following is the code to add the same Icecreams objects to the ArrayList, as we did in the previous example.

    ArrayList arrListIcecreams = new ArrayList();
    arrListIcecreams.Add( new Icecream {Name="Chocolate Fudge Icecream",
        Ingredients="cream, milk, mono and diglycerides...",
        Cholesterol="50mg", Protein="4g", TotalCarbohydrates="35g",
        TotalFat="20g", Price=10.5 });
    arrListIcecreams.Add( new Icecream {Name="Vanilla Icecream",
        Ingredients="vanilla extract, guar gum, cream...",
        Cholesterol="65mg", Protein="4g", TotalCarbohydrates="26g",
        TotalFat="16g", Price=9.80 });
    arrListIcecreams.Add( new Icecream {Name="Banana Split Icecream",
        Ingredients="Banana, guar gum, cream...", Cholesterol="58mg",
        Protein="6g", TotalCarbohydrates="24g", TotalFat="13g", Price=7.5
    });

 

Following is the query to fetch low priced ice-creams from the list.

 

    var queryIcecreanList = from Icecream icecream in arrListIcecreams
    where icecream.Price < 10
    select icecream;

 

Use the foreach loop, shown as follows, to display the price of the objects retrieved using the above query.

    foreach (Icecream ice in queryIcecreanList)
    Console.WriteLine("Icecream Price : " + ice.Price);




Reading from Strings

We all know that a string is a collection of characters. It means that we can directly query a string value. Now let us take a string value and try to find out the number of upper case letters in the string. For example, assign a string value to the variable aString as shown below.

    string aString = "Satheesh Kumar";

Now let us build a query to read the string and find out the number of characters that are in upper case. The query should be of type IEnumerable.

    IEnumerable<char> query =
    from ch in aString
    where Char.IsUpper(ch)
    select ch;

 

The query uses the Char.IsUpper method in the where clause to find out the upper case letters from the string. The following code displays the number of characters that are in upper case:

    Console.WriteLine("Count = {0}", count);
   

Reading from Text Files

A file could be called a collection, irrespective of the data contained in it. Let us create a text file that contains a collection of strings. To get the values from the text  file, we can use LINQ queries. Create a text file that contains names of different ice-creams. We can use the StreamReader object to read each line from the text file. Create a List object, which is of type string, to hold the values read from the text file. Once we get the values loaded into the strings List, we can easily query the list using LINQ queries as we do with normal collection objects. The following sample code reads the text file, and loads the ice-cream names to the string list:

 

    List<string> IcecreamNames = new List<string>();
    using( StreamReader sReader = new StreamReader(@"C:Icecreams.txt"))
    {
        string str;
        str = sReader.ReadLine();
        while (str != null)
        {
            IcecreamNames.Add(str);
        }
    }

 

The following sample code reads the list of strings and retrieves the name of ice-creams in descending order:

    IEnumerable<string> icecreamQuery =
    from name in IcecreamNames
    orderby name descending
    select name;

 

We can verify the result of the query by displaying the names using the following code:

    foreach (string nam in icecreamQuery)
    {
        Console.WriteLine(nam);
    }

 

The following code displays the names and verifies the result of the query:

    foreach (string nam in icecreamQuery)
    {
        Console.WriteLine(nam);
    }

Similar to collections used in above examples, the .NET reflection class library can be used to read metadata of the .NET assembly and create the types, type members, parameters, and other properties as collections. These collections support the IEnumerable interface, which helps us to query using LINQ.

LINQ has lot of standard query operators which can be used for querying different objects that support IEnumerable interface. We can use all standard query operators, listed in the following table, against objects.

Query Operator type

Query Operators

Restriction

Where, OfType

Projection

Select, SelectMany

Joining

Join, GroupJoin

Concatenation

Concat

Sorting

OrderBy, OrderByDescending, ThenBy, ThenByDescending, Reverse

Set

Distinct, Except, Intersect, Union

Grouping

GroupBy

Conversion

AsEnumerable, Cast, OfType, ToArray, ToDictionary, ToList, ToLookup

Equality

SequenceEqual

Element

DefaultIfEmpty, ElementAt, ElementAtOrDefault, First, FirstOrDefault, Last, LastOrDefault, Single, SingleOrDefault

Generation

Empty, Range, Repeat

Quantifi ers

All, Any, Contains

Aggregation

Aggregate, Average, Count, LongCount, Max, Min, Sum

Partitioning

Skip, SkipWhile, Take, Takewhile

Summary

In this article, we saw some examples to query different objects using LINQ operators. We can use LINQ queries on any object that supports IEnumerable. By using LINQ, we can avoid using looping methods to loop through the collections and fetch the required details. LINQ provides powerful filtering, ordering, and grouping methods. This will reduce our coding as well as the development time.

This article has been taken from the book LINQ Quickly

Similar Articles