Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does a const int implicitly cast to a byte, but a variable int does not?

Tags:

c#

.net

clr

The following program will not compile:

   class Program
   {
      static void Main(string[] args)
      {
         int x = 50;
         Byte[] y = new Byte[3] { x, x, x };
      }
   }

Not surprisingly, I will get the error Cannot implicitly convert type 'int' to 'byte'

However, if I make x a const, then it will compile:

   class Program
   {
      public const int x = 50;

      static void Main(string[] args)
      {
         Byte[] y = new Byte[3] { x, x, x };
      }
   }

I'm curious as to what's going on here. If an int cannot be implicitly cast to a byte, does the compiler create a "byte" version of my const on the fly, or does it compile it as if I had put in an explicit cast, as it deems the constant value "safe" for a byte? Perhaps the compiler interprets this as if I had written:

Byte[] y = new Byte[3] { 50, 50, 50 };

It makes since that this is legal, I'm more curious as to what the compiler is doing here.

like image 214
Mike Christensen Avatar asked Jan 29 '12 01:01

Mike Christensen


4 Answers

I refer you to section 6.1.9 of the C# 4 specification, which states:

A constant expression of type int can be converted to type sbyte, byte, short, ushort, uint, or ulong, provided the value of the constant expression is within the range of the destination type.

Your question was:

does the compiler create a "byte" version of my const on the fly, or does it compile it as if I had put in an explicit cast, as it deems the constant value "safe" for a byte?

I don't understand the difference between those two things; they sound like the same thing to me.

like image 75
Eric Lippert Avatar answered Nov 14 '22 21:11

Eric Lippert


The compiler will just treat the constant as if you wrote the number there, but there needs to be an implicit conversion.

In your third snippet, those three 50 are all System.Int32. Hover your mouse over it and read the tooltip in Visual Studio. Why doesn't the compiler error here? Because the compiler knows the value at compile time and knows it will fit inside a byte.

like image 40
Marlon Avatar answered Nov 14 '22 21:11

Marlon


The non-constant value has the potential to be too large for a Byte, whereas the constant value is constant and guaranteed to be below the threshold in this case.

like image 39
Justin Pihony Avatar answered Nov 14 '22 23:11

Justin Pihony


Constants are 'baked-in' at compile time.

One noteworthy consequence of how constants are compiled is that if you compile against an assembly, it will use the constant values at the time of compilation. If you later bind against a different version of the assembly at runtime, it will use the original constants, even if they have changed in the new version of the assembly. This also applies to Enum constants, in particular. The moral of the story is that (public) constant values really should be constant; if there is any possibility of a meaningful change occurring, use a static readonly field instead.

like image 22
Dan Bryant Avatar answered Nov 14 '22 23:11

Dan Bryant