Tuesday, August 16, 2011

New Object Oriented Features in C# 3.0

Implicitly Typed Local Variables
var age = 30;

Implicitly Typed Arrays
var numbers = new[] { 1, 2, 3, 4, 5};
var names = new[] { "Dave", Doug, "Jim" };


Auto Implemented Properties
old:
public int ID
{
get{return _id;}
set{_id = value;}
}

new:
public int ID { get; set; }

Object Initializers
old:
Person obj = new Person();
obj.ID = 1;
obj.FirstName = "Thiru";
obj.LastName = "Thangarathinam";
new:
Person obj = new Person { ID = 1, FirstName = "Thiru", LastName = "Thangarathinam" };

Collection Initializers
old:
List names = new List();
names.Add("David");
names.Add("Tim");
names.Add("Doug");
new:
List names = new List {"David", "Tim", "Doug"};

Anonymous Types

As the name suggests, anonymous types allow you to create a type on-the-fly at compile time. The newly created type has public properties and backing fields defined for the members you initialize during construction. For example, consider the following line of code:

var obj=new{ID=1,FirstName="Thiru",LastName="Thangarathinam"};

In the above line, you just specify the various attributes you want to have in the anonymous class and assign the instantiated object to a variable of type "var". The actual type assigned to obj is determined by the compiler. Since the compiler assigns the name of the type only at compile time, you can't pass an anonymous type to another method and it can only be used within the method they were declared.

When the compiler sees the above code, it automatically declares a class as follows:

class __Anonymous1
{
private int _id = 1;
private string _firstName = "Thiru";
private string _lastName = "Thangarathinam";

public int ID
{
get{return _id;}
set{_id = value;}
}
public string FirstName
{
get{return _firstName;}
set{_firstName = value;}
}
public string LastName
{
get{return _lastName;}
set{_lastName = value;}
}
}

Anonymous Types use the Object Initializer to specify what properties the new type will be declare. This allows us to reduce code looking similar to this:

Note that the anonymous types are just meant to be placeholders for quickly defining entity types and you can't add methods or customize the behavior of an anonymous type.


Extension Methods

Another important feature introduced with C# is the ability to add new static methods to existing classes, known as extension methods. Using this new feature, you can extend the built-in classes (such as the String class) to support your custom requirements. For example, you can add a new method named "IsValidZipCode" to the string class that validates the zip code format. Let us discuss the code required to accomplish this:

namespace StringExtensions
{
public static class CustomStringExtension
{
public static bool IsValidZipCode(this string input)
{
Regex regEx = new Regex(@"^\d{5}$");
return regEx.IsMatch(input);
}
}
}

As part of the declaring the arguments for the IsValidZipCode, you specify the name of the type to which the extension method should be added as the first parameter. In this case, since we want the IsValidZipCode method to be added to the string class, you specify string as the first parameter. Once you are inside the IsValidZipCode() method, you can access all of the public properties/methods/events of the actual string instance that the method is being called on. In this example, you return true or false depending on whether it is a valid zip code or not.

Now that you have implemented the extension method, the next step is to invoke it from the client application. To be able to do that, you first need to import the namespace in which the CustomStringExtension is located.

using StringExtensions;

Once you have imported the namespace, the next step is to declare a variable of type string and invoke the IsValidZipCode() method.

private void btnTestExtensionMethod_Click(object sender, EventArgs e)
{
string zip = "85226";
if (zip.IsValidZipCode())
MessageBox.Show("Valid Zipcode format");
else
MessageBox.Show("Invalid Zipcode format");
}

As you can see from the preceding lines of code, the extension methods allow you to write cleaner and easy-to-maintain code.

Here are some of the key characteristics of extension methods:

  • The extension method as well as the class that contains the extension method should be static.
  • Although extension methods are static methods, they are invoked as if they are instance methods.
  • The first parameter passed to the extension method specifies the type on which they operate and it is preceded by the "this" keyword.
  • From within the extension method, you can't access the private variables of the type you are extending.
  • Instance methods take precedence over extension methods in situations where they have same signature.

Lambda Expressions


Anonymous methods is a new feature introduced with C# 2.0 that enables you to declare your method code inline instead of with a delegate function. Let us take a look at a simple anonymous method:

public Forms()
{
check = new CheckBox(...);
text = new TextBox(...);
checkBox.CheckedChanged += delegate
{
text.Text = "...";
};
}

As you can see in the above code, you don't have to explicitly declare a new method to link it with an event. C# 3.0 introduces an even simpler syntax, lambda expressions, which you write as a parameter list followed by the "=>" token, followed by an expression or a statement block.

Lambda expressions are simply functions and they are declared in the context of expressions than as a member of a class. It is an inline expression or a statement block which can be used to pass arguments to a method or assign value to delegate. All lambda expressions use the lambda operator => and the left side of the operator denotes the results and the right side contains the expression to be evaluated. For instance, consider the following lambda expression:

age => age + 1

The above function takes one argument named age, and returns age + 1 as the result. As you can see, Lambda expressions follow the below syntax:

(parameter-list) => expression;

where expression can be any C# expression or a block of code. Just like anonymous methods you can use a lambda expression in place of a delegate. Here are some sample lambda expressions and their corresponding delegates.

//Explicitly typed parameter
(Person obj) => MessageBox.Show(obj.FirstName.ToUpper());

//Implicitly typed parameter
(obj) => obj.FirstName == "Thiru";

//Explicitly typed parameter
(int a, int b) => a + b

//Implicitly typed parameter
(x, y) => { return x + y; }

As you see from the preceding lines of code, lambda expressions can be written in such a way that it can infer the parameter type from the signature of the delegate it is assigned to.


No comments: