How does var work for numbers?
Asked Answered
C

1

6

I experimented today with how the compiler determines the types for numbers declared as var.

var a = 255; //Type = int. Value = byte.MaxValue. Why isn't this byte?
var b = 32767; //Type = int. Value = short.MaxValue. Why isn't this short?
var c = 2147483647; //Type = int. Value = int.MaxValue. int as expected.
var d = 2147483648; //Type = uint. Value = int.MaxValue + 1. uint is fine but could have been long?
var e = 4294967296; //Type = long. Value = uint.MaxValue + 1. Type is long as expected.

Why is int the default for any number that is between Int32.MinValue and Int32.MaxValue?

Wouldn't it be better to use the smallest possible data type to save memory? (I understand that these days memory is cheap, but still, saving memory isn't that bad especially if it's so easy to do).

If the compiler did use the smallest data type, and if you had a variable with 255 and knew that later on you would want to store a value like 300, then the programmer could just declare it short instead of using var.

Why is var d = 2147483648 implicitly uint and not long?

Seems as though the compiler will always try and use a 32 bit integer if it can, first signed, then unsigned, then long.

Cadet answered 21/5, 2018 at 10:51 Comment(0)
C
3

Seems as though the compiler will always try and use a 32 bit integer if it can, first signed, then unsigned, then long.

That is exactly right. C# Language Specification explains that it tries to pick an integral type that uses the smallest possible number of bytes to represent integer literal with no suffix. Here is the explanation from the language specification:

To permit the smallest possible int and long values to be written as decimal integer literals, the following two rules exist:

  • When a decimal-integer-literal with the value 2147483648 and no integer-type-suffix appears as the token immediately following a unary minus operator token, the result is a constant of type int with the value −2147483648. In all other situations, such a decimal-integer-literal is of type uint.
  • When a decimal-integer-literal with the value 9223372036854775808 and no integer-type-suffix or the integer-type-suffix L or l appears as the token immediately following a unary minus operator token, the result is a constant of type long with the value −9223372036854775808. In all other situations, such a decimal-integer-literal is of type ulong.

Note that the language specification mentions your var d = ... example explicitly, requiring the result to be of type uint.

Choosy answered 21/5, 2018 at 11:10 Comment(3)
I wonder why out of byte, short, int, uint, long, ulong, they decided to only use int/uint and long/ulong?Cadet
@Backwards_Dave I think they did it for practicality. Typically int and uint are the fastest types for integer operations. Arithmetical operations on byte and short usually perform the operation on int, and then truncate it back to fit in the original type. If C# were to use this rule for shorts and bytes, things like for (var i = 0 ; ... ) would end up generating pretty inefficient code.Choosy
Yes you're right. @Evk provided a good example in the question's comments.Cadet

© 2022 - 2024 — McMap. All rights reserved.