Friday, February 10, 2012

New Features in C# 4.0

Each version of C# has a number of new features and generally a major theme. The major themes have been generics and nullable types in C# 2.0, LINQ in C# 3.0, and dynamic types in C# 4.0. The major features added in each release are generally considered to be the following:
  • C# 2.0—Generics (.NET Framework support was added, and C# benefited from this); iterator pattern (the yield keyword); anonymous methods (the delegate keyword), nullable types, and the null coalescing operator (??).
  • C# 3.0—Anonymous types, extension methods, object initializers, collection initializers, implicitly typed local variables (var keyword), lambda expressions (=>), and the LINQ query expression pattern.
  • C# 4.0—Optional Parameters and Named Arguments, Dynamic typing (dynamic type), improved COM-Interop, and Contra and Co-Variance.

 

Dynamic Lookup

C# 4.0 provides access to the Dynamic Language Runtime (DLR) using the new ‘dynamic’ keyword in .NET4, allowing dynamic languages like Ruby and Python to expose their objects to C#. Apart from consuming objects from dynamic languages, this feature also helps us in implementing customized dynamically dispatched objects. This can be done by implementing the IDynamicObject interface, which itself is usually done by inheriting from the abstract DynamicObject class and providing our own implementation and invocation; the IDynamicObject interface allows us to interoperate with the DLR and implement our own behavior!
Before we can go into what Dynamic type is and how it acts, we need to have a basic understanding about DLR and its components, so we’re going to spend a bit of time investigating this new feature.

Dynamic Language Runtime (DLR)

The DLR is the new API in .NET Framework 4 that is responsible for implementing dynamic programming, and is common runtime for the dynamic languages. The C# runtime is built on the top of the DLR in order to give provision for the dynamic typing. The below figure illustrates the block diagram of the DLR and its internal components.
The Dynamic Runtime Language
Fig 1: C#4.0 dynamic programming, and how DLR works.
The languages with dynamic capabilities (such as C#4.0 and VB 10.0) are built on top of the DLR which, as we can see above, has three main components at it’s core:
1. Expression Trees
2. Dynamic Dispatch
3. Call Site Caching
An Expression Tree depicts code in the form of a tree, which allows languages to be translated into a standard design on which the DLR can operate. These are the same kind of expression trees that were introduced in C# 3 LINQ, but which have now been improved to support statements. Once code is in a tree representation, the DLR can take the tree and use it to generate CLR code.
Dynamic Dispatch is the process of mapping messages to sequences of code at runtime . This is the way that the system lets the binders decide on the target method. Code is generated for dynamic invocations to the appropriate Language Binders.
Call Site Caching is used to avoid the need to call into the binder. Normally the binder returns an expression tree which the DLR compiles, but this step can be avoided if the types of the arguments are the "same".
Speaking of the binders, these exist beneath the DLR, and are responsible for communicating with the respective environments of different technologies. For example, the Object binder allows communication with .NET Objects, the JavaScript binder allows communication with JavaScript in Silverlight, the Python and Ruby binders allow to communication with their respective languages, and the COM binder allows communication with Office / COM Objects.
All of this is wrapped up in the DLR, which C# 4.0 provides access to using the new ‘dynamic’ keyword. This permits data types to be decided dynamically at runtime, as opposed to statically at compile-time, by redirecting any calls involving a parameter of type dynamic through the DLR. Dynamic type signifies to the compiler that all operations based on that type should (unsurprisingly) be inferred dynamically, and instructs the compilerto ignore the compile time checking for this type.
The C# compiler now allows for calling a method with any name and any arguments on dynamically created object types. Consider the code below.
dynamic d = GetNum();d.divide(40,5); // allows us to call any method with any signature..
As d is declared as dynamic, the compiler will not generate any runtime errors for the above declaration and, although it will still engage in type checking, it will not decide the target data type of the call until runtime; so the actual object that is being dynamically referred to will be determined at runtime. As mentioned in the code annotation above, the compiler allows calling dynamic objects with any method or signature. Here is diagrammatic representation of how it works:
Dynamic demonstration 1
Fig 2: The Dynamic keyword in action.
Dynamic Demonstration 2
Figure 3: Method invocation
Because C# is a statically typed language, the ‘dynamic' type informs the compiler that it is working with a dynamic invocation, and so can forget about the normal compile-time checking for that type. However, this also means that illegal operations (if any) will only be detected at runtime.

The Difference between Var and Dynamic

People often get confused between var and dynamic, so I would like to you to understand exactly what is meant by each keyword.
If the ‘var’ keyword is used, the data type is still determined by the compiler at compile time. On the other hand, when the ‘dynamic’ keyword is used, the member and method lookups are determined at runtime. In addition, dynamic can also be used as the return type for methods, and the Var keyword cannot be used for procedure return calls.
In addition, the dynamic keyword will not give you trouble if it doesn't have any associated method. On the other hand, var will never allow the application to compile if any method is used which is not associated with it.

Optional Parameters

Microsoft’s coevolution in C# and VB languages has made this feature possible now. These parameters need to be declared with a default value in the method signature, and allow for omitting arguments to member invocations. The below example describes the syntax:
private void CreateNewStudent(string name, int studentid = 0, int year = 1)

The method above can be called in any of the following ways:
CreateNewStudent("Sukanya"); //Equivalent to Sukanya,0,1CreateNewStudent("Prakash", 16); //Equivalent to Prakash,16,1CreateNewStudent("Pinal", 40, 2); //Equivalent to Pinal,40,2

In the above code, it is mandatory to pass the name, but the remaining two parameters are optional. If we do not pass any of the values in those parameters, then the default values are passed.
Note: The Optional Parameters must be placed after the required parameters, or else the C# compiler will show a compile time error.

There are a few limitations to the optional parameters feature, and we’ll look at them after we’ve considered the new Names Arguments feature, as the two are very useful when deployed together..

Named Arguments

Named arguments are a way to provide an argument using the name of the desired parameter, instead of depending on its [the parameter’s] position in the parameter list. Now, if we want to omit the studentid parameter value in the above code, but specify the year parameter, the new named arguments feature (highlighted below) can be used. All of the following are also valid calls:
CreateNewStudent("Jacob", year: 2);CreateNewStudent(name: "Andrew", studentid: 30, year: 2);CreateNewStudent("Vamshi", studentid: 4);CreateNewStudent(year:2, name:"Hima", studentid: 4); //changing the order

Named arguments are the best way to write self-documenting calls to your existing methods, even if they don’t use optional parameters. Not only can an argument use the name of the relevant parameter, but we can also change the position of the parameter if desired.

 The example below shows how to make use of optional and named arguments:
private static void CreateNewStudent(string name, int studentid = 0, int year = 1){
Console.WriteLine
("Name = " + name + " : "+"StudentID = " + studentid + " : "+"Year = " + year); }static void Main(string[] args){
CreateNewStudent
("Sukanya");CreateNewStudent("Prakash", 16); CreateNewStudent("Pinal", 40, 2);CreateNewStudent("Jacob", year: 2);CreateNewStudent(name: "Andrew", studentid: 30, year: 2);CreateNewStudent("Vamshi", studentid: 4);CreateNewStudent(year: 2, name: "Hima", studentid: 4);Console.ReadLine();}
Although Visual Studio’s IntelliSense doesn’t deal very well with Dynamic, it works perfectly well for named and optional parameters.:
Intellisense working with Names and Optional parameters
Fig 4: Named and Optional parameters IntelliSense.
The demonstration code above produces the output seen in Figure 5's console window:
Named and Operational parameters in action
Fig 5: Named and Optional parameters

Limitations

As much as a I wish it were otherwise, Named and optional parameters do not permit arguments to be omitted between commas. A Method signature applies if all parameters are optional or have a corresponding argument identified by name or position in the method call. As such, the following calls are not accepted by the C-sharp Complier, because the omitted optional arguments are being ignored:
CreateNewStudent("Hima", ,); // Not permitting arguments to be omitted between comas,
    // although logically it should take default values for the other two parameters.
CreateNewStudent(3,0); // Overload cannot convert string to integer. If the first
                       // parameter is string, it will automatically infer it as name.

No comments:

Post a Comment