Monday, March 16, 2009

New Features in C# 3.0 / .NET 3.5 Part 3

This is the third part of the New Features in C# 3.0 / .NET 3.5 series. Part 1 can be found here and Part 2 can be found here.

The next thing I'd like to cover is a new keyword introduced in .NET 3.5 which is the "var" keyword. From MSDN:

Local variables can be given an inferred "type" of var instead of an explicit type. The var keyword instructs the compiler to infer the type of the variable from the expression on the right side of the initialization statement. The inferred type may be a built-in type, an anonymous type, a user-defined type, or a type defined in the .NET Framework class library.
In simple terms, when declaring a local variable, you no longer need to specify what type of variable it is on the left hand side of the assignment call. For example:

   int x = 10;

is just the same as this:

   var y = 10;

It's important to note that this is NOT a dynamic type that's available in other languages like PHP or python. With dynamic types (which will be available in .NET 4.0) the compiler does NOT know at design time what Type the variable will be. It will be figured out at runtime. With C# type inference though, the compiler knows full well what the type will be. It can figure it out from what's on the right hand side. Now I know you're probably thinking "what's the point of this? how hard is it to just type a few extra letters?" Well, imagine if you have something like this:

Dictionary<string, List<StringBuilder>> dictionary = new Dictionary<string, List<StringBuilder>>();


Well don't you think it'd be neater if we had this?

var dictionary = new Dictionary<string, List<StringBuilder>>();

At first it may not seem like a big deal but you'll find yourself starting to use it quite often. The thing to point out though is that the "var" keyword can ONLY be used for variables that are local in scope. They can not be used for class level variables. This would NOT compile:

    public class MyClass
    {
        var myVariable = new StringBuilder(); //compile error
        public MyClass()
        {
            var varIable = new StringBuilder(); //this is fine
        }
    }

You're probably STILL thinking, "what's the use? Why bother??". Well, this leads me to the next new feature in .NET 3.5. The real reason these things were created was for something called "Anonymous Types". From MSDN:

Anonymous types provide a convenient way to encapsulate a set of read-only properties into a single object without having to first explicitly define a type. The type name is generated by the compiler and is not available at the source code level. The type of the properties is inferred by the compiler. The following example shows an anonymous type being initialized with two properties called Amount and Message.
Anonymous types allow you to create a new type on the fly. For example:

        public void MyMethod()
        {
            var myNewObject = new
            {
                stringProperty = "Hello, World!",
                intProperty = 1337,
                boolProperty = false
            };
        }

At this point, C# has actually created a new type for us with the read-only properties that we specified in our declaration of the Anonymous Type. Again, this type is only within the scope of this method, but we can now actually dot into myNewObject as if it were a real object from a concrete class. For example:

            var myNewObject = new
            {
                stringProperty = "Hello, World!",
                intProperty = 1337,
                boolProperty = false
            };
 
            Console.WriteLine(myNewObject.stringProperty); //output: "Hello, World!"
            Console.WriteLine(myNewObject.intProperty); //output: 1337
            Console.WriteLine(myNewObject.boolProperty); //output false

And this is what Intellisense looks like:



As you can see, Intellisense picks up all the properties of our Anonymous Type. The interesting thing here is that a concrete type is actually created for us by the compiler. By inspecting the IL this is what we find:



What's really interesting here, is that if somewhere else in your app you have another Anonymous Type that looks just like this one, the C# compiler is smart enough to only create one class of that Type. It has to be the exact same set of parameters with the same name and in the exact order.

To prove this, there's a known "hack" out there that allows you to actually return an anonymous type from a method (contrary to what I said before that Anonymous Types are only local in scope). Consider this:

        public object MyMethod()
        {
            var myNewObject = new
            {
                stringProperty = "Hello, World!",
                intProperty = 1337,
                boolProperty = false
            };
 
            return myNewObject;
        }

Our same anonymous type as before, only now we're actually returning this from a method. Now, here's the cool part:

        public T Cast<T>(object obj, T type)
        {
            return (T)obj;
        }

A generic method that takes Object as a parameter, then an object of type T as the second parameter. It then casts obj to the type of T. Here's how we can now use this:

       var obj = MyMethod();
       var myNewObj = Cast(obj, new { stringProperty = "",
intProperty = 0, boolProperty = false });



Now here's where we prove that C# only creates ONE class for that anonymous type. We passed in as the second parameter to the Cast method a new anonymous types with different values. However, since the parameters are the same and the order is the same, we can cast obj (the return value from our method) to the SAME TYPE as the new anonymous type. If C# created two separate classes, this would never work!

This isn't my trick, and I wouldn't recommend using this in production code, but it gets the point across.

1 comment:

rkumar said...

The matter has been written in very a simple and understandable style. Its great , keep going, all the best