While this may be true, I don't trust that is is true in the case of Mono. The version of Mono used in unity is janky in a number of ways -- foreach causes heap allocations!! When we moved over from native .NET to mono, there were a number of things that had been perfectly great in performance that suddenly were disasters on the CPU or RAM or GC or all of the above.
It has to be true, it's how var works. var doesn't exist in the runtime, the compiler figures out what it is and makes the IL code for that. Mono could derive something weird, I guess, but it has to derive *something* at compile time. Thus, there's no performance cost there.
This, too. There are plenty of cases where type can't be correctly inferred, too. Is an integer-looking number an int32? uint? Int64? Etc. A lot of times that doesn't matter, but sometimes it does. And I don't really care for having all my integers defaulting to 64bit just because we're on a 64bit system; frankly short and ushort should be used a lot more than they are. And actually I guess that really should be int16 and uint16; I don't know if short got remapped to int32 on 64bit machines.
And a lot of times that will vary by machine and compile parameters. If you're hoping for sim-concurrence in a game that can desync, then even float isn't precise enough thanks to differences in FPUs; there are cases where you can get away with it by using a double, but in general we use fixed-int math instead for the ultimate in predicability (and bitshifts are handy with that, too).
It's a funny mess, the ecosystem of various implementations of the .NET spec...
Can you even do that in C#? I know if I do this:
var x = 14;
It's an int. The spec says so. It's *always* an int, unless it can't be represented as an int. The only other way it's not an int is if I tell it otherwise:
var x = 14L;
That one would be a long. There is, oddly, no way to do this for a short. But unless there's a button somewhere I haven't seen in C#, someone can't come along and change what "int" means, which means var is very consistent in what you get out of it.
Or in the monster of a method signature I wrote yesterday:
(Java)
private <T extends Comparable<T>, V extends T,U extends Comparable<U>, W extends U> void addArbitraryOre(String orename, IBlockState flower, IBlockState desertFlower, @Nullable IProperty<T> flowerProp, @Nullable V flowerValue, @Nullable IProperty<U> desertProp, @Nullable W desertValue) { ... }
Technically I could shorten the generics to <T extends Comparable<T>, U extends Comparable<U>> and remove the @Nullable annotations, but given the method I pass these parameters to (and isn't mine) uses "V extends T" I figured I should match. This was just an internal helper method anyway.
But using "var" would be too dangerous.
My Java is rusty, but I'm pretty sure using var would be a compiler error there, because it returns void. There's no type for var to infer.