Click here to monitor SSC
  • Av rating:
  • Total votes: 106
  • Total comments: 19
Amirthalingam Prasanna

.NET Collection Management with C# 3.0

25 February 2008

Using C# 3.0 to manage a collection of objects

Generics in C#, enable you to define classes, interfaces, delegates or methods with placeholders for parameterized types used within. This allows you to define classes that use a generic type, and define the type at the time of instantiation or method calls. This makes your code strongly typed, but makes maintenance easier. Prasanna describes the improvements in .NET v3.5

This article looks into some of the new features in C# 3.0 and introduces Linq in managing a collection of objects within a generic List

Introduction

A couple of years ago, I wrote an article entitled “.NET Collection Management” for Simple-Talk. The purpose of that article was to introduce generics and to show how generics can be used to manage a collection of strongly typed objects within a generic List using C# 2.0. Generics allow us to write code without binding the code to a particular type, and at the same time ensures we can use strongly typed objects. I thought I’d revisit the article to see how much my code would be simplified and improved in C# 3.0, and introduce some of the new features in C# 3.0.

Let us define an Employee class that we will be using throughout the examples in this article. The Employee class has the properties Name and Salary.

public class Employee

{

    public string Name { get; set; }

    public double Salary { get; set; }

}

We have omitted the implementation of the properties because their implementation is very simple.  You set a value to a private field and get the value from a private field. So we are going to let the compiler implement the properties for us. This is a feature called “Automatic Properties” that saves a few lines of code and improves the readability of the code when the property implementation is very simple.

Next we will define and use a collection of Employee objects using a List<T>.

List<Employee> col = new List<Employee>();

col.Add(new Employee() { Name = "John", Salary = 25500 });

col.Add(new Employee() { Name = "Smith", Salary = 32000 });

 

In this code, we have used a special syntax in initializing the property values at the time of creating Employee objects. This is a feature called “Property Initialization” that provides a very easy way of initializing one or more properties when creating an object.

Sorting a List

We can use the Comparison delegate and pass it into the Sort method of List<Employee>. In the following code we will use an anonymous method to pass the instance of a Comparison delegate to do the sorting operation. The anonymous method simplifies the call to the Sort method since we do not need to define a separate method.

col.Sort(delegate(Employee emp1,Employee emp2)

{

    return emp1.Salary.CompareTo(emp2.Salary);

});

 

We could have written this code in C# 2.0. But in C# 3.0 we can further simplify the implementation by using Lambda expressions for method implementations. Lambda expression is an inline method implementation that is translated to an instance of a delegate by the compiler. These expressions use the syntax “(parameter 1, parameter 2 …) => method implementation”. Lambda expressions allow us to define methods on the fly with a simpler syntax compared to anonymous methods. So the above code can be simplified by using the Lambda expression syntax as follows:

col.Sort((emp1, emp2) => emp1.Salary.CompareTo(emp2.Salary));

By using the Lambda expression, I have omitted defining the type for emp1 and emp2. Since the Sort method accepts an instance of a Comparison delegate for Employee objects, the compiler is intelligent enough to understand that emp1 and emp2 has to refer to Employee objects. The expression “(emp1, emp2) => emp1.Salary.CompareTo(emp2.Salary)” will be translated to an instance of the Comparison delegate.

Another way of sorting the generic List is by using the static method Enumerable.OrderBy. This method will return an ordered collection of Employee objects

IEnumerable<Employee> orderedEmp = Enumerable.OrderBy<Employee, double>(col, (emp) => emp.Salary);

The OrderBy method is an extension method. An “Extension method” is a new feature in C# 3.0 that allows you to call a static method belonging to a class as if it is an instance method  belonging to an object. This also allows us to extend types which normally we might not be able to extend. So the OrderBy method can be called as if it is an instance method because it is an extension method. The compiler would replace it as a call to the static Enumerable.OrderBy extension method:

IEnumerable<Employee> orderedEmp = col.OrderBy<Employee,double>((emp) => emp.Salary);

Searching a List

The generic List has the methods Find or FindAll to search for one or more objects within the List. Both these methods accept an instance of the Predicate delegate as a parameter. The Predicate delegate instance can be defined by creating a method or an anonymous method or a lambda expression.

We can also use the Enumerable.Where extension method to search within the generic List. The following code segment returns a collection of Employee objects where the Salary property value is greater than 1000.

IEnumerable<Employee> empsWithBigSalary = col.Where((emp) => emp.Salary > 1000);

Operations on objects within List

There are many operations that are available through extension methods that can be performed on objects within a List. Most of these operations require looping through the objects within the collection. But with the use of extension methods, we can perform these operations without the need to loop through the collection.

For example let us assume we want to retrieve the maximum Salary amount within the collection of Employee objects within List<Employee>. We can use the Max extension method as show in the below code:

double max = col.Max((emp) => emp.Salary);

Similarly we can use many other operations such as Min, Sum, and Count that are available.

List Conversion

Converting a List of one type to a List of another type is very simple. We can still use the Converter delegate that was available in C# 2.0. Another way of converting the type of a List is to use the Enumerable.Select extension method.

IEnumerable<string> empNames = col.Select<Employee, string>((emp) => emp.Name);

This method call would return a collection of employee names. However, let‘s assume that we want to convert the collection of Employee objects into a collection of objects that has the name of the employee and a boolean value indicating whether the employee has a salary over 1000. We would need to create a new type as a class or a structure that has a string property and a boolean property. C# 3.0 supports a new feature called “Anonymous Types” that allows us to define types on the fly.

var emps = col.Select((emp) => new { Name = emp.Name, BigSalary = emp.Salary > 1000 });

We’ve defined a new type that has the properties Name and BigSalary. Another thing that you might have noticed here is the use of the new keyword “var”. This is a new feature called “Type Inference”.  Type inference is used when we do not know the name of the type of the variable and we require the compiler to help us out in inserting the name of the type. This is used with anonymous types, since the compiler defines the type anonymously.

Linq

We went through sorting, searching, performing operations and converting a collection of Employee objects in a generic List. The extension methods OrderBy and Where returns an IEnumerable of the type that we use within the generic List – in this instance the Employee type. The extension method Select return an IEnumerable of the type we want to convert the employee objects to. We can combine these extension methods to search, sort and convert the objects within the generic List

IEnumerable<string> emps = col.

    Where((emp) => emp.Salary > 1000).

    OrderBy((emp) => emp.Salary).

    Select((emp) => emp.Name);

This is where Linq comes in. Linq stands for Language INtegrated Query and provides a SQL like syntax for accomplishing what we did in the above code.

IEnumerable<string> emps = from emp in col

                           where emp.Salary > 1000

                           orderby emp.Salary

                           select emp.Name;

This code uses Linq to query the collection of Employee objects. The syntax is very similar to SQL except that  the select clause is at the end of the query expression. It makes sense because the process of converting the objects within the generic List would be the last step. Each expression in the Linq statement followed by the where, orderby and select keywords are lambda expressions. These lambda expressions are used to make method calls to the extension methods as shown in the above examples.

Conclusion

This article looks at the capabilities of the new features in C# 3.0 that helps to better handle collection of objects. It also introduces language integrated query and how it helps in managing collections.

Amirthalingam Prasanna

Author profile:

Prasanna is a software engineer, technical author and trainer with many years of development and consulting experience in the software development industry. He is a Microsoft MVP in the Visual developer category, and a MCPD on enterprise application development. He has authored many articles and has worked on content creation for many Microsoft certification exams and courses. He is also a frequent speaker at Microsoft technology conferences and events. You can read his blog at www.prasanna.ws and e-mail him at feedback@prasanna.ws

Search for other articles by Amirthalingam Prasanna

Rate this article:   Avg rating: from a total of 106 votes.


Poor

OK

Good

Great

Must read
Have Your Say
Do you have an opinion on this article? Then add your comment below:
You must be logged in to post to this forum

Click here to log in.


Subject: Quick Tip
Posted by: Merill Fernando (not signed in)
Posted on: Monday, February 25, 2008 at 3:51 PM
Message: Good article.

You can event omit the () when using object initializers.

new Employee() { Name = "John", Salary = 25500 }

can be written as

new Employee { Name = "John", Salary = 25500 }

Cheers!

Subject: Well Done
Posted by: Srikanth (view profile)
Posted on: Monday, February 25, 2008 at 10:14 PM
Message: I knew that you are a big fan of Collections framework. Great work indeed.

Subject: Simply Elegant
Posted by: Amber (not signed in)
Posted on: Tuesday, February 26, 2008 at 5:51 AM
Message: I had learned C and C++ four years ago for my exams and promptly forgotten both the languages after the exams. This article has helped me recall a few of the forgotten coding principles of C and C++. It has also helped me gain insight into the world of C#. What more can i say! A few more such articles and some practice exercises and I'll be able to tell C# like the back of my hand.

Subject: It must reach
Posted by: Sathiyaseelan Arulanandam (not signed in)
Posted on: Tuesday, February 26, 2008 at 9:51 PM
Message: Mr. Amirthalingam Prasanna has given strong and versatile introductions with a very...very... simple understandable smooth flow example

Actually one developer can change the style by your great article in 30 minutes....
Guru knows how to feed shiya :)..yes that is true.


Subject: Nice work
Posted by: alasdair cs (not signed in)
Posted on: Wednesday, February 27, 2008 at 8:28 AM
Message: Good article - particularly the smooth explanation of linq as successive application of lambda expressions to extension methods.

Subject: Nice acticle
Posted by: Tim (view profile)
Posted on: Wednesday, February 27, 2008 at 1:35 PM
Message: I initially scrolled through it trying to find the C# 3.0 stuff but, not finding it, read the entire article. Nice way of incorporating the new features in your article! I never knew you could use anonymous methods in C# 2.0. I'm definitely loving lambda expressions now though.

Subject: article. Nice way of incorporating the
Posted by: Anonymous (not signed in)
Posted on: Thursday, February 28, 2008 at 1:36 AM
Message: article. Nice way of incorporating the new features in your article! I never knew you

Subject: Thanks
Posted by: Ben (view profile)
Posted on: Thursday, February 28, 2008 at 2:11 AM
Message: Thanks - this makes me want to get myself a copy of Visual Studio 2008 and have a play! I hope the 90 days you get with the evaluation will be sufficient!

Subject: hi
Posted by: Anonymous (not signed in)
Posted on: Thursday, February 28, 2008 at 3:26 AM
Message: that it

Subject: asp.net + C#
Posted by: Anonymous (not signed in)
Posted on: Thursday, February 28, 2008 at 3:28 AM
Message: how i can make the commints as this in asp.net

my email : abctawil@yahoo.com

pleas send to me.

Subject: .NET 3.5
Posted by: Anonymous (not signed in)
Posted on: Friday, February 29, 2008 at 11:02 AM
Message: I'm sorry to correct you, but all the stuff you are talking about was introduced in .NET 3.5.
.NET 2.0 is merely a collection of new APIs like Workflow Foundation, Presentation Foundation and doesn't change anything at the .NET 2.0 base language.
Regards
René

Subject: .NET 3.5
Posted by: Anonymous (not signed in)
Posted on: Friday, February 29, 2008 at 11:02 AM
Message: I'm sorry to correct you, but all the stuff you are talking about was introduced in .NET 3.5.
.NET 3.0 is merely a collection of new APIs like Workflow Foundation, Presentation Foundation and doesn't change anything at the .NET 2.0 base language.
Regards
René

Subject: Re: .NET 3.5
Posted by: Prasanna (view profile)
Posted on: Friday, February 29, 2008 at 12:18 PM
Message: Yes , All the features I hv mentioned here are of .NET 3.5 as specified in the article. C# 3.0 is part of .NET 3.5. In .NET 3.0 we used the same C# 2.0 version with no changes from .NET 2.0.

Subject: hi
Posted by: Nagaraj L Gowda (not signed in)
Posted on: Friday, May 09, 2008 at 5:33 AM
Message: Good article

Subject: ebook about c#
Posted by: javad (not signed in)
Posted on: Thursday, May 15, 2008 at 11:32 AM
Message: please send a good ebook about c#
my Gmail: mjsh86mech@Gmail.com

Subject: Version Numbers
Posted by: DrFooMod2 (not signed in)
Posted on: Monday, May 26, 2008 at 6:36 PM
Message: The versioning of .NET lately is idiotic. 3.0 should have been 2.1 (or 2.5 at best), and the latest should be 3.0. That way C# 3.0 matches the Fx version. Duh.

Subject: Thanks
Posted by: Willy Wang (view profile)
Posted on: Thursday, June 04, 2009 at 10:55 PM
Message: Good article. Thank you.

Subject: great article
Posted by: sandy060583 (view profile)
Posted on: Friday, September 18, 2009 at 7:35 AM
Message: hi Prasanna,

Really a Great Article,

You have Explained C# 3.0 features with Collections very smoothly & Effectively.

Your way of writing explanation is excellent.

Subject: To the Point.. Good Article
Posted by: kuldeep rana (view profile)
Posted on: Thursday, May 17, 2012 at 12:19 AM
Message: To the Point.. Good Article

 

Top Rated

Acceptance Testing with FitNesse: Multiplicities and Comparisons
 FitNesse is one of the most popular tools for unit testing since it is designed with a Wiki-style... Read more...

Acceptance Testing with FitNesse: Symbols, Variables and Code-behind Styles
 Although FitNesse can be used as a generic automated testing tool for both applications and databases,... Read more...

Acceptance Testing with FitNesse: Documentation and Infrastructure
 FitNesse is a popular general-purpose wiki-based framework for writing acceptance tests for software... Read more...

TortoiseSVN and Subversion Cookbook Part 11: Subversion and Oracle
 It is only recently that the tools have existed to make source-control easy for database developers.... Read more...

TortoiseSVN and Subversion Cookbook Part 10: Extending the reach of Subversion
 Subversion provides a good way of source-controlling a database, but many operations are best done from... Read more...

Most Viewed

A Complete URL Rewriting Solution for ASP.NET 2.0
 Ever wondered whether it's possible to create neater URLS, free of bulky Query String parameters?... Read more...

Visual Studio Setup - projects and custom actions
 This article describes the kinds of custom actions that can be used in your Visual Studio setup project. Read more...

.NET Application Architecture: the Data Access Layer
 Find out how to design a robust data access layer for your .NET applications. Read more...

Calling Cross Domain Web Services in AJAX
 The latest craze for mashups involves making cross-domain calls to Web Services from APIs made publicly... Read more...

Web Parts in ASP.NET 2.0
 Most Web Parts implementations allow users to create a single portal page where they can personalize... Read more...

Why Join

Over 400,000 Microsoft professionals subscribe to the Simple-Talk technical journal. Join today, it's fast, simple, free and secure.