Published: 30 May 2011
By: Sanjeev Singh
Download Sample Code

C# 3.0 introduced some of very useful features built on top of 2.0. This article explains the usage, syntax and reasoning behind those language features.

Contents [hide]

Automatic backing fields support for properties

Typically a property on a class is declared in two steps:

  1. Define a private backing field. For example: private string _name;
  2. Define public properties that encapsulate the backing field. For the above backing field the property would be declared like: public string Name { get { return _name; } set { _ name = value; } }

A question that we may ask is: "why do we need to encapsulate the field when we are doing just nothing in the property getter and setter? "

And the simple answer to this question is: "While today the property methods are not doing anything with the field. However in future, before accessing the field some business validation may be required. But if the fields are made public in the first release, the client code will start consuming the fields directly. In future when fields are encapsulated by property methods, to enforce business rules, it will break the code contract with the consumers. To avoid this problem we expose public properties backed by private fields."

C# 3.0 introduced backing fields, which actually makes the two step process into just single step without compromising anything. From C# 3.0 onwards you can define a property, without defining its backing field the compiler will automatically generate the backing store for the property.

For example, the person class in code below is a legal class.

Object Initializers

Before C# 3.0, to initialize an object of a class meant two things:

  1. Create an instance of the class
  2. Initialize the public properties of the object.

A typical initialization would look like as shown below:

C# 3.0 allows writing very compact code to achieve the same: For example now you can write the initialization code like

This is actually a compiler magic, where compiler substitutes the verbose code when it encounters an inline initialization. But the source code remains concise and clean.

This way you can initialize nested properties. For example imagine if Person had a property called Father of type Person. In such case the initialization would look like:

The object initialization becomes real handy when initializing a collection. For example, if a list of person has to be created with containing 3 person it can be done like this:

Or it can be done like:

var type or type inferencing

Many a times the declaration looks like a unnecessary repetition especially with generics. For example:

The declaration of type of the variable is redundant. It can be easily determined by looking at what is on the right hand side of the assignment operator. Similarly there are scenarios where compiler can determine the type of the variable on the Left Hand Side of assignment operator.

var is a keyword in C# 3.0, which mean the type of the variable will be determined by the compiler by evaluating what is on the RHS of the assignment operator. It shortens the declaration. The above example becomes:ù

The following code snippet shows more examples of var:

As you can see the type inferencing makes the code look cleaner and concise.

Please note that var is neither object nor does it compromises the type-safety. The compiler substitutes var with appropriate type before the compilation. If you inspect the IL code, you will find exact type of the variable instead of var.

Anonymous types

Many a times we create a class that are actually neither required in business logic nor outside a method. They are required temporarily to hold a group of values. C# 3.0 allows us to create types without assigning a name to them. However such classes can't be passed out of the function

This is another compiler magic. It allows declaring an inline class in a method without actually giving a formal name to the type. For example

In the above snippet, an anonymous type is created with three properties. The syntax shown above is understood by compiler. The compiler defines a temporary class, with two public properties (Name, Designation and Age) and creates an instance of that class. The class is creation is not visible in the code but can be seen in the MSIL. See the image given below:

Figure 1: IL showing the compiler generated class

IL showing the compiler generated class

The compiler actually creates a class in the backend and assigns a name to it. The name of the class can be determined by inspecting IL or calling GetType method on the object itself. Visual studio provides full intellisense around anonymous types.

One question that comes to mind after seeing such anonymous types is how to create methods on such types.

Extension methods

Many times we wish that some additional method was available on a type that is written by someone else (either FCL or some third party library). Before C# 3.0, to do so you would inherit from the base class and add new method. This works but everywhere you must use the derived type rather than the original type. Extension methods solves this problem nicely by allowing you to declare new methods without changing the actual class that can be invoked as if they were on the original class itself. An example would be very handy here.

For example assume that you want a method called, IsPalindrome on string class that should return true if the string value is actually a palindrome otherwise return false.

To define your new extension methods, create a static class. Add a static function to the newly added class. The name of the functions should be exactly what you want to add to the already existing class, in this case it will be IsPalindrome. The first argument to this function should be pre-fixed by this keyword and the type of the first argument should be same as that of the base class . In this case type is string.

Lambda Expressions

Lambda expressions are a compact notation to define anonymous functions(introduced in C#2.0) so that they can be passed to other functions as parameter.

LINQ

LINQ combines all the features that we discussed so far and provides a natural querying syntax that is same for querying in memory objects, xml or database. LINQ is not the focus of this article so we will not go into details of LINQ. But just to show LINQ in action, below is a code snippet to select only Name and Age of people whose name start with "A".

When used to query data from database, LINQ becomes an ORM tool.

Summary

Morpheus says in movie Matrix: "There is difference between knowing the path and walking the path". Similarly, "There is difference between knowing the feature and using it". These features will make your code look cleaner and at the same time increase your productivity.

<<  Previous Article Continue reading and see our next or previous articles

About Sanjeev Singh

Sorry, no bio is available

View complete profile here.

Other articles in this category


C# 4.0 Reflection Programming - Part 1
An introduction to Reflection in C#.
C# 4.0 Reflection Programming - Part 2
As introduced in the first article, the most typically-used tools associated with .NET reflection ar...
C# 4.0 Reflection Programming - Part 3
In the previous article, we used the reflection to obtain the information of an assembly, module, ty...
C# 4.0 Reflection Programming - Part 4
In this last article of this series, we will learn what to do with reflection. But before making the...
Understanding and Using Extension Methods
Extension methods were new to C# 3.0. They allow you to add a method to an existing type without hav...

You might also be interested in the following related blog posts


Training on Xamarin.iOS with iOS 7: Introduction and Features read more
Training on Xamarin.iOS with iOS 7: Introduction and Features read more
An Introduction to Sql 11 (Code Name Denali) Part VI (T-Sql Features in CTP 3) read more
Quick introduction to the Web Load Test features of Visual Studio 2010 read more
Introducing SharePoint 2010 Training at U2U read more
Examining ASP.NET 2.0's Membership, Roles, and Profile - Part 17 read more
Introducing Versatile DataSources read more
How to Limit Access to Administrator Modules in DotNetNuke 5 - 5 Videos read more
New article: How to detect and avoid memory and resources leaks in .NET applications read more
Screencast Whats new in the Entity Data Model Designer in VS2010 read more
Top
 
 
 

Please login to rate or to leave a comment.