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.
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.
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
.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With