August 4, 2008
@ 09:55 AM

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.

  1. Implicit conversions
  2. Intellisense

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)
   7: {
   8:     return sku.value;
   9: }

In order to test this method I have the following code:

   1: [Test]
   2: public void Implicit_conversion_of_sku_to_string()
   3: {
   4:     string skuValue = "ZZ123456";
   5:     var sku = new ProductSKU(skuValue);
   6:  
   7:     var converted = sku;
   8:  
   9:     Assert.That(converted, Is.EqualTo(skuValue));
  10: }

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:

image

(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.

Intellisense

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?

image 

image

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.


 
Monday, August 04, 2008 10:27:07 AM (Central Standard Time, UTC-06:00)
Tim,

What do you mean by "the reintroduction of var"?

I do see your point about losing Intellisense when defining something like Dictionary<string,string>. It's definitely an annoyance.

Chris
Monday, August 04, 2008 10:32:59 AM (Central Standard Time, UTC-06:00)
I suppose "reintroduction" was a misnomer. I was implying that most of us probably came from a non-static code background, ie. classic ASP, where var was common. Now we have "var" in our statically typed language. I should have been clearer, sorry about that.
Monday, August 04, 2008 11:22:06 PM (Central Standard Time, UTC-06:00)
I am not big on var myself. I can't really explain why, but I think you put some of it into words for me. I like to be implicit only every once in awhile. Keeps the bugs out. :D
Monday, August 04, 2008 11:30:54 PM (Central Standard Time, UTC-06:00)
I use var constantly and I don't understand why people care whether or not I use the var keyword.
Tuesday, August 05, 2008 5:11:54 AM (Central Standard Time, UTC-06:00)
@Gabriel

It's not that I'm against it's usage, I'm only advocating that one be careful in it's usage and to make sure you know what's going on. As Robz points out he likes being explicit and in certain situations as I show above, being explicit is less error prone.
Tuesday, August 05, 2008 10:48:18 AM (Central Standard Time, UTC-06:00)
Both your arguments are nonsense.

The actual point of the unit test in the first example is to test conversion from ProductSKU to string. How does that test do that? The only conceivable way to write that is as:

string skuValue = "ZZ123456";
var sku = new ProductSKU(skuValue);
string converted = sku;

The problem isn't that DID use var; the problem is that you DIDN'T use string. Had you specified "ProductSKU" or "int" or whatever as the type for converted, it would have been just as wrong. Don't blame the language because you have a bug in your code.

Your Intellisense argument is just as silly: Yes, you have to 'type out enough information from which intellisense can narrow down what I'm looking for'. Yes, you do.... Always. Using var, you have to type at the end of the line. WITHOUT var, you have to type it out at the beginning of the line. Either way, you have to type it out once on that line. Where's the problem?

Tuesday, August 05, 2008 11:06:05 AM (Central Standard Time, UTC-06:00)
@James

I'm not "blaming" language. The post is meant to caution users on just typing var and letting the compiler figure it out. There was no bug it was an illustration in how if you're not careful you will not test what you wanted to test in the first place.
Tuesday, August 05, 2008 11:51:21 AM (Central Standard Time, UTC-06:00)
My point is that the only correct way to write that line is:
string converted = sku;

Now imagine that var didn't exist, but you had written:
int converted = sku;

Would we be having the same discussion about the need to be careful using "int"? Probably not, but the code is still wrong, for exactly the same reason.

Now consider had we written it as:
ProductSKU converted = sku;

(which, in effect, is the way it was written). Everything you could say about the original is true for that. And again, clearly the problem here is not var.

Essentially, your argument boils down to "The existence of 'var' makes me think the compiler can read my mind, and I am disappointed when it can't."




Tuesday, August 05, 2008 6:49:50 PM (Central Standard Time, UTC-06:00)
Yeah, what James said re intellisense.

Let's imagine I'm typity typing the declaration.
(forgive me if I've gotten the intellisense completion characters wrong, I'm a VB'er natively)

Dict [left angle] stri [comma] stri [right angle] myList = new [semicolon]

vs

var myList = new Dict [left angle] stri [comma] stri [right angle] [semicolon]

Seems about the same to me either way.

I love your work Tim (really, I do!), but this one seems a little... silly :)
Dan F
Tuesday, August 05, 2008 7:02:10 PM (Central Standard Time, UTC-06:00)
@Dan,

I actually agree with you. My point wasn't that NOT typing var is easier, it's that, as you pointed out, you have to type it either way. When the new features of c# 3.0 were announced I heard a few times how you won't have to type out declarations, especially nasty little generic collections. My point here is to disagree with them, and agree with you, you have to type it either way!
Wednesday, August 06, 2008 6:44:22 PM (Central Standard Time, UTC-06:00)
Hehe, I really should learn to read more eh :)
Dan F
Wednesday, August 06, 2008 7:00:39 PM (Central Standard Time, UTC-06:00)
@Dan

Gotta be hard to read with that patch over your eye!
Comments are closed.