Overload Resolution and Covariance
As of C# 4.0, generics support covariance and contravariance. I won’t talke about contravariance in the post, however.
To sum it up quickly, covariance enables implicit conversion of a generic collection of type T to the same generic collection of a type that derives from T. In short:
IEnumerable<Object> list = new List<String>().AsEnumerable();
This means that as of now, any method that accepts something like IEnumerable<Object> can accept an IEnumerable<String> as well. This changes the overload resolution mechanism:
class A { } class B : A { } class T { internal void Foo(IEnumerable<B> sequence) { Console.WriteLine("In T.Foo.B"); } } class U : T { internal void Foo(IEnumerable<A> sequence) { Console.WriteLine("In U.Foo.A"); } }
In the following code, how does the method resolution changes?
U u = new U(); var l = new List<A>(); var m = new List<B>(); u.Foo(l); u.Foo(m);
If ran in Visual Studio as a .NET 3.5 application, here is the result:
If ran in Visual Studio as a .NET 4.0 application, here is the result:
Prior to C# 4.0, U.Foo was not a candidate for a call using a generic collection of B. However, with covariance, it is, hence the different result. So, this is no breaking change, but the behavior of an application might be affected.
The Misunderstood var Keyword
I find amazing how the var keyword introduced in C# 3.0 is misunderstood.
The web is full of questions asking what are the performances implications of using var, of how var is not type safe and other completely false statements.
Also, one a day, I had a discussion with colleagues that argued that if I was using var, I could also use Object as the type for all the variables and then cast everywhere.
I don’t know why the var appears so misleading. I find it very simple, and have no issues using it a lot. Now, there are some readability discussion to using var, but that is purely subjective.
Everything Happens at Compile-Time
The very important concept that has to be understood is that with var, everything happens at compile time. You make the compiler work a little more when building your assembly, but the generated IL is exactly the same than if you explicitly use types.
So, the performances are only at compile time, and frankly, who cares of the performances at compile time?
Let’s go over this again.
Look at this code and the generated IL:
static void Main(string[] args) { var s = "Hello"; }
.method private hidebysig static void Main(string[] args) cil managed { .entrypoint .maxstack 1 .locals init ( [0] string s) L_0000: nop L_0001: ldstr "Hello" L_0006: stloc.0 L_0007: ret }
Now the same code, using var instead of String:
static void Main(string[] args) { var s = "Hello"; }
.method private hidebysig static void Main(string[] args) cil managed { .entrypoint .maxstack 1 .locals init ( [0] string s) L_0000: nop L_0001: ldstr "Hello" L_0006: stloc.0 L_0007: ret }
Exactly the same IL. Exactly.
To quote MSDN:
It is important to understand that the var keyword does not mean "variant" and does not indicate that the variable is loosely typed, or late-bound. It just means that the compiler determines and assigns the most appropriate type.
It cannot be more clear!
So please, stop picking on the poor var. Go pick on dynamic.
"Calling a method on null a reference" by Jon Skeet
Two months ago, I wrote a blog post called Extension Methods and null Objects. In this post, I described how to write Extension Methods in C# 3 and wrote a small sample code to add IsNullOrEmpty as an extension method to the String class. Well, guess what, I found that particular example in a book.
A few weeks ago, I bought Jon Skeet’s book C# in Depth, and have been reading it trough since then (I have to say that it is very well written and a pure joy to read, highly recommended if you are somewhat familiar with C# and would like to polish your knowledge of the language).
Reading part 10.2.4, "Calling a method on a null reference", I was surprised to discover that Jon used exactly the same example as I did! Well, I have to admit that it is I that used the same example as him, as it was already long printed when I wrote that post.
At first it seems odd to be able to call IsNullOrEmpty on a variable that is null without an exception being thrown, particularly if you’re familiar with it as a static method from .NET 2.0. In my view, code using the extension method is more easily understandable. For instance, if you read the expression if (name.IsNullOrEmpty()) out loud, it says exactly what it’s doing.
Nevertheless, I was very pleased with myself and, dare I say it, immediately thought "Great Minds Think Alike" :p.
Extension Methods and null Objects
C# 3.0 allows adding new methods to existing types. These are called Extension Methods. This allow programmers to add methods to existing types, even if they are not partial or event sealed.
These special methods have to be declared in a special way:
- They must be declared within a static class
- They must be static
- The first parameter of the method has to be the type that is "extended", preceded by the this keyword
So, for example, let’s copy the very useful IsNullOrEmpty method as an extension method.
public static class Extensions { public static bool IsNullOrEmpty(this String s) { return String.IsNullOrEmpty(s); } }
String s = ""; s.IsNullOrEmpty();
returns true. You can even do
"".IsNullOrEmpty();
which returns true as well.
Now, all of this is actually an illusion. When the compilers finds
"".IsNullOrEmpty();
Extensions.IsNullOrEmpty("");
So, when an extension method is used, there is one more parameter, that is of the type the extension method is defined on. In this case, String.
But, if it as parameter, it can be null, right? Yes!
String s = null; s.IsNullOrEmpty();
or even
((String) null).IsNullOrEmpty()
will both work, without trowing a NullReferenceException.
Nothing revolutionary here, but I found funny to "call" method on a null object and not have an exception raised.
