Last week, I stumbled upon the following piece of code:
IList<double> doubles = new List<double> {22.123, 400.12, 100.22}; foreach (int number in doubles) { Console.WriteLine("The Current Number Is : {0}", number); }
Can you see the bug in that code? We convert all of the doubles in the list to integers, truncating them. I was very surprised that the compiler didn’t warn me about this issue, especially because the compiler would not let me write this code:
double someDouble = 22.523; int someInt = someDouble;
An explicit conversion is necessary here:
int someInt = (int)someDouble;
What is the difference between those two cases? Can’t I expect a uniform behavior from the compiler? The reason is probably historic - before C# 2.0 which introduced us with Generics, all of the containers held their items as objects. If the foreach statement didn’t automatically do the conversion, the user would have to explicitly cast every item in the collection from object…
ArrayList array = new ArrayList {"moshe", "levi"}; foreach (object obj in array) { string str = obj as string; if (str != null) Console.WriteLine("The Current element is {0}", str); }
In most cases, the collection items are of the same type so in order to reduce the explicit conversion effort, the C# developers decided to do an automatic conversion for us. If we test the MSIL which is generated for the foreach statement, we can clearly notice to the “injected” code which is responsible for the conversion:
![]()
Now that we understand what happens, here is a way to avoid those kinds of bugs. Using the var keyword, we can ask the compiler to define the type of the collection item according to its value. Here it is:
IList<double> doubles = new List<double> {22.123, 400.12, 100.22}; foreach (var number in doubles) { Console.WriteLine("The Current Number Is : {0}", number); }
By changing this code, the compiler is responsible for determining the type of “number”. In most cases, that is exactly what we want…
We pay for user submitted tutorials and articles that we publish. Anyone can send in a contribution
Learn More
Frank Quednau Said on Jul 28, 2009 :
In cases where some type provides you only with a non-generic IEnumerable you will be provided with object as the var type. THat may not be what you want. The implicit casting is a remnant of 1.1 days, I don’t think it would be too necessary right now, alas, the non-generic interfaces are still around.
Frank Quednau Said on Jul 28, 2009 :
Forget my comment…
Oisin G. Said on Jul 29, 2009 :
bwt, when you say “an implicit conversion is needed here”, you really mean an explicit one…
Josh Said on Aug 4, 2009 :
Sob, I didn’t see the problem. You’ve really taken a solid look at the whole casting situation here. Thx for making your results available.