C# Programming: Language Enhancements in C# 4.0

Introduction

As we saw the features of Microsoft Visual Studio 2010 and ASP.NET 4.0 in my previous articles we will look into the new language enhancements in C# 4.0 in this article. 4.0 is the version of C# language that is bundled along with the .NET framework 4.0. There is a 1 hour video available on channel 9 in which the C# 4.0 design team discusses its new features here. Also you should check Microsoft's website called CSharpFuture where you could find many tutorials and code samples.

Dynamic Nature of C# 4.0

If you closely look at how C# language is being evolved during the recent times then you will realize the fact that it is moving slowly to the dynamic side from its static type checking nature. A good example would be the introduction of generics in C# 2.0, anonymous types, etc. Now in the 4.0 version there is a great deal of support for dynamic programming.

For example in the dynamic programming it is left to the runtime to infer the type of an object and process it accordingly. This offers a good amount of flexibility to the language. The only drawback could be since the actual type checking is done during the runtime you are at a higher risk of getting runtime exceptions. So should be extremely careful while coding.

This dynamic inferring of types at runtime is made possible in C# 4.0 because of a component called Dynamic Language Runtime (DLR) which is a part of the .NET framework 4.0.

Dynamic Keyword

There is a new keyword for specifying the member type in C# 4.0 called 'dynamic'. As the name indicates the type of a dynamic object is not static and it is totally dynamic. You can assign object of any type to the dynamic variable which will be inferred at the runtime and executed accordingly. The best part is that in the dynamic objects you can make use of the methods, properties or indexers dynamically. To me this has really a big advantage for the developers since they don't have to use different variables for different types.

Let us check the program below

namespace CSharp4Samples
{
    class Program
    {
        static void Main(string[] args)
        {
            //declare adynamic object and assign a generic list
            dynamic dynamicObject = GetGenericList();
            //dynamically adds a string
            dynamicObject.Add("codeguru.com from generic list");
            //dynamically access the indexer
            Console.WriteLine("The dynamic object value is: {0}", dynamicObject[0]);

            //now assign a array list
            dynamicObject = GetArrayList();
            //add the string dynamically
            dynamicObject.Add("codeguru.com from array list");
            //dynamically access the indexer of array list
            Console.WriteLine("The dynamic object value is: {0}", dynamicObject[0]);

            Console.ReadKey();
        }

        /// <summary>
        /// Gets a generic list object
        /// </summary>
        /// <returns></returns>
        private static dynamic GetGenericList()
        {
            List<string> list = new List<string>();
            return list;
        }

        /// <summary>
        /// Gets a array list object
        /// </summary>
        /// <returns></returns>
        private static dynamic GetArrayList()
        {
            ArrayList list = new ArrayList();
            return list;
        }
    }
}

In the above code check how the objects of an array list and a generic list are stored in the same variable dynamicObject which is of type dynamic. Also see the fact that the Add method and the indexers are being accessed so dynamically. As I said earlier in the dynamic approach you should be very careful since there is a good chance of doing a mistake which will go unnoticed during compile time.

Fig 1.0 shows the output window


Fig 1.0

In languages like IronPython and Ruby the dynamic objects will extensively implement the interface IDynamicObject. So in a C# application if the dynamic object implements IDynamicObject then the DLR will leave the whole operation to the dynamic object itself.

C# Programming: Language Enhancements in C# 4.0

Enhancements in COM interaction

The COM interaction has been improved by means of little menaces that are faced by most developers. Here are some of them:

  1. When you make use of COM library in your C# application a Primary Interop Assembly (PIA) is created for the COM library which is being used, the created PIA adds quite considerable size to the application. With C# 4.0 PIA's are not required anymore which is a big relief.
  2. In the earlier versions of C# when you use COM libraries the return type of methods and type of the properties in the COM methods are mostly objects, so you have to typecast it while fetching it. Now the return types are of dynamic instead of object so you can directly assign or fetch the value without any typecasting. Below is an example where excel interop has been used:

    //Check this
    //in the earlier versions of C# you have to assign the value to a cell like
    ((Excel.Range)worksheet.Cells[1, 1]).Value2 = "COM interaction sample";
    //now in C# 4.0 since the return type is dynamic type casting is not required.
    worksheet.Cells[1, 1].Value2 = "COM interaction sample";
    

  3. Another thing is in many COM methods you see the parameters being passed by reference with the keyword ref. This cannot be avoided in the previous versions of C# but with 4.0 you can simply pass the parameters by value and skip the ref keyword, instead the compiler will generate automatic variables to hold the passed in parameter values.

    For example check the below code which has used the Word interop

          object missing = Type.Missing;
          Word.Application application = new Word.Application();
          //In earlier versions on C#
          application.Documents.Add(ref missing, ref missing, ref missing, ref missing);
          //Now you can simple skip ref
          application.Documents.Add(null, null, null, null);
    

  4. In the previous versions of C# in order to get an element from an indexed collection you have to use the get_Item rather than using the index directly like how we do with C# indexers. This is now made possible.

    Here is the sample code:

          object missing = Type.Missing;
          Word.Application application = new Word.Application();
          application.Documents.Add(null, null, null, null);
          //In earlier versions on C#
          Word.Document doc = application.Documents.get_Item(0);
          //No you can access it like
          doc = application.Documents[0];
    

Covariance & Contravariance

I am sure that this topic would be a little confusing for most developers. For understanding this you should be clear with what was possible and what was not in the previous versions of C# while assigning one object to another.

In C#, a type of higher hierarchy can accept a type of lower hierarchy and the vice-versa is not (in this case it would give you a compile time error).

string stringText = "www.codeguru.com";
//This is perfectly fine, since object is in a higher hierarchy than string
object objectText = stringText;
//This will throw a compile time error
stringText = objectText;

But take the case of collections like a List of object and a list of string, assigning the list of string to the object list was disallowed because there is a chance for the developer to assign an int value in the object list where a string is actually stored, this is a clean violation of type safety.

But there are instances where the collection can only be assigned and cannot be modified like this:

IEnumerable<string> stringEnumerable = GetStringCollection();
IEnumerable<object> objectEnumerable = stringEnumerable;

In the IEnumerable collection the value cannot be modified. Even then this was not allowed to avoid confusion in the earlier C# versions. But in C# 4.0 this is made possible by concepts called as Covariance and Contravariance.

Covariance

Allowing an object having parent type as generic argument to be assigned with an object having derived type as generic argument is covariance and it is achieved by using our keyword.

See the below C# example:

//Here is the out declaration which makes Covariane possible
interface ICovarianceDemo<out T> { }
//Implementation class
class CovarianceDemo<T> : ICovarianceDemo<T>
{
public CovarianceDemo(T type)
       {
                Console.WriteLine("My type is {0}", typeof(T));
       }
}
//Parent class
class Animal { }
//Derived class
class Tiger : Animal { }

static void Main(string[] args)
{
//Build an object having generic argument as derived type
       ICovarianceDemo<Tiger> tigerObject = new CovarianceDemo<Tiger>(new Tiger());
       //Pass it to the method
       DoSomething(tigerObject);
       Console.ReadKey();
}

/// <summary>
/// Method which accepts an object having generic argument as parent type
/// </summary>
static void DoSomething(ICovarianceDemo<Animal> animalObject)
{
}

If you remove the out key word from the ICovarianceDemo declaration then there will be a compile time error. So, now we are able to assign animalObject with tigerObject with the use of covariance.

Contravariance

Allowing an object having derived type as generic argument to be assigned with an object having parent type as generic argument is contravariance and it is achieved by using in keyword.

See the below C# example:

//Here is the in declaration which makes Contravariance possible
interface IContravarianceDemo<in T> { }
//Implementation class
class ContravarianceDemo<T> : IContravarianceDemo<T>
{
     	public ContravarianceDemo(T type)
       {
       	Console.WriteLine("My type is {0}", typeof(T));
       }
}
//Parent class
class Animal { }
//Derived class
class Tiger : Animal { }

static void Main(string[] args)
{
//Build an object having generic argument as parent type
       IContravarianceDemo<Animal> animalObject = new ContravarianceDemo<Animal>(new Tiger());
       //Pass it to the method
       DoSomething(animalObject);
       Console.ReadKey();
}

/// <summary>
/// Method which accepts an object having generic argument as derived type
/// </summary>
static void DoSomething(IContravarianceDemo<Tiger> tigerObject)
{
}

If you remove the in key word from the ICovarianceDemo declaration then there will be a compile time error. So, now we are able to assign tigerObject with animalObject with the use of contravariance.

Note that the same can be applied to delegates as well. There are many examples available on the net which explains covariance and contravariance using delegates, including this one by Mark Strawmyewr titled, Safe Covariance and Contravariance in .NET 4.0.

Limitations

  • It only works for interfaces and delegates not for Generic classes and Structs
  • It will only work when the type arguments are reference type and it does not work for value types.

C# Programming: Language Enhancements in C# 4.0

Optional Parameters and Named Arguments

Optional Parameters

This is a nice enhancement that has been made for the C# language. Just imagine you are writing a method which takes in 100 parameters and another developer who is making use of your method but wants to pass the value only to 3 parameters and for the rest he wishes to pass in only the default values like null, String.Empty, 0, etc, in such cases the optional arguments feature comes into play and is very useful which will make your code less messy and save you time and effort.

Note that it cannot be applied with the existing library usage because the method parameter declaration part has to be modified. How do we make the parameters as optional, it is so simple to just specify the default value in the method's parameter declaration.

Here is the sample C# program:

namespace CSharp4Samples
{
    class Program
    {
        static void Main(string[] args)
        {
            //Do not pass any value
            OptionalParameterDemo();
            //Pass only the name
            OptionalParameterDemo("Johny");
            //pass both name and age
            OptionalParameterDemo("Johny", 25);
        } 

        /// <summary>
        /// 
        /// </summary>
        /// <param name="name">is optional and default value is DefaultStringValue</param>
        /// <param name="age">is optional and default value is 10</param>
        private static void OptionalParameterDemo(string name = "DefaultStringValue", int age = 10)
        {
            Console.WriteLine("Name is {0} and Age is {1}", name, age);
        }
    }
}

See the method OptionalParameterDemo method parameters name and age are set as optional. Fig 2.0 is the output window.

[system2.jpg]
Fig 2.0

The only thing I found hard is the optional parameter at the end which can be skipped while calling i.e., you cannot provide the age and skip the name value. For such scenarios you should combine the optional parameters feature with the named parameters feature.

Named Arguments

This is a feature which will allow you to pass arguments based on the name immaterial of the order in which they are passed. You can compare this to that of passing the parameters to a SQL server stored procedure using the ADO.NET framework where the parameters values are passed by the parameter name and not based on the position index.

How do you pass the argument based on the parameter name? It is simple while sending the value prefix it with the parameter separated by colon.

I have modified the above C# program to introduce the named argument features.

namespace CSharp4Samples
{
    class Program
    {
        static void Main(string[] args)
        {
            //pass only the age using named argument feature
            OptionalParameterDemo(age: 100);
        } 

        /// <summary>
        /// 
        /// </summary>
        /// <param name="name">is optional and default value is DefaultStringValue</param>
        /// <param name="age">is optional and default value is 10</param>
        private static void OptionalParameterDemo(string name = "DefaultStringValue", int age = 10)
        {
            Console.WriteLine("Name is {0} and Age is {1}", name, age);
        }
    }
}

See in the above program only the age value is passed skipping the value for the 'name' parameter.

Fig 2.1 is the output window:

[system3.jpg]
Fig 2.1

Conclusion

I hope this article shows you the important new features of C# 4.0. The one which attracted me the most was the dynamic type which has really taken the C# language to new heights.



About the Author

V.N.S Arun

I work for an MNC in Bangalore, India. I am fond of writing articles, posting answers in forums and submitting tips in dotnet. To contact me please feel free to make use of the "Send Email" option next to the display name.

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: September 16, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you starting an on-premise-to-cloud data migration project? Have you thought about how much space you might need for your online platform or how to handle data that might be related to users who no longer exist? If these questions or any other concerns have been plaguing you about your migration project, check out this eSeminar. Join our speakers Betsy Bilhorn, VP, Product Management at Scribe, Mike Virnig, PowerSucess Manager and Michele …

  • Not long ago, security was viewed as one of the biggest obstacles to widespread adoption of cloud-based deployments for enterprise software solutions. However, the combination of advancing technology and an increasing variety of threats that companies must guard against is rapidly turning the tide. Cloud vendors typically offer a much higher level of data center and virtual system security than most organizations can or will build out on their own. Read this white paper to learn the five ways that cloud …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds