I posted earlier this year with the basic question, Is Var Better? I'm not the only one to question the reintroduction of var. Rhys Campbell went as far as to say some abuse the new keyword. I will say that my initial aversion to using var has softened a bit. However there are at least two issues I have with them.
- Implicit conversions
In my latest project I've encapsulated all domain knowledge in it's own assembly in DDD fashion. We have the notion of a ProductSku, a unique identifier for a product. A Product object therefore has a ProductSku property which identifies it. I could have implemented the ProductSku property as a string type, but in thinking about my domain and remembering March is Not a Number ProductSku is now it's own first-class citizen type.
I have the following code to perform implicit conversion from a ProductSku to a string:
1: /// <summary>
2: /// Performs an implicit conversion from <see cref="JPCycles.Domain.ProductSKU"/> to <see cref="System.String"/>.
3: /// </summary>
4: /// <param name="sku">The sku.</param>
5: /// <returns>The result of the conversion.</returns>
6: public static implicit operator string(ProductSKU sku)
8: return sku.value;
In order to test this method I have the following code:
2: public void Implicit_conversion_of_sku_to_string()
4: string skuValue = "ZZ123456";
5: var sku = new ProductSKU(skuValue);
7: var converted = sku;
9: Assert.That(converted, Is.EqualTo(skuValue));
As you can see in line 7, I'm using the var keyword. The problem with this is that using var in the scenario keeps me from testing the code that I want to test. The goal of the test is to confirm the implicit conversion of a ProductSku to string. This happens in line 7. However when using the var keyword, the compiler interprets the "converted" variable as a ProductSku object and not a string object, as I really want.
See below for confirmation:
(You might be saying to yourself that the conversion still happens in line 9, when the ProductSku object is evaluated against a string. You might be right? Or...does the string get implicitly converted to a ProductSku object? If you don't know the answer to that question off the top of you head you cannot rely on line 9 for your conversion. Also you shouldn't be using your asserts to perform the work for which you are testing)
If I leave the var keyword in place in line seven, my test will pass and possibly deceive me into thinking I've properly tested my code. Only when running a coverage report do I see that the implicit conversion method is never being called.
The use of var is fine, except that now I have to think about how the compiler will interpret a statement versus what I want in programming it. The var keyword does the best it can, but sometimes that's not good enough. As another example, compare the following code:
1: IUser user1 = new User();
2: var user2 = new User();
The two users above have different type signatures, which on some level bothers me a bit, since you can see that the code is clearly the same.
The use of var makes intellisense less effective. It's not the compilers fault though. Given the point where you use var, the compiler has no idea what you're going to type on the right-hand side of the expression, so it cannot help.
Say, for example, I want to define a Dictionary<string,string> called "my list". When I use the var keyword, I have to type out enough information from which intellisense can narrow down what I'm looking for. I hear a lot from the proponents of var how great it is because complex declarations, especially with generics, can be avoided. I disagree and only need to show you the example below to prove my point. In the example below I'm writing the exact same line of code. The first example uses var, the second does not, which would you prefer?
When using var I had to type everything since the compile cannot help me, only I had to type on the right hand side of the expression. So I really have saved nothing.
Jeff Atwood posted that by not using var, you're being redundant. I would say that by not being redundant, for which the compiler penalizes you nothing, you're being slower, because you cannot take advantage of build-in assistance, ie intellisense.
These two annoyances won't stop me from using var in various (read: limited) situations. The point of this post is to caution the reader to not be too quick to jump on the var bandwagon. In the first example it may cause you headaches in performing proper testing and in the second, it may slow you down with the loss of intellisense.