1

Assigning an int literal to a byte variable is legal:

byte b = 123;   // legal

However, assigning an int variable to a byte variable is illegal:

int i = 123;
byte b = i;     // illegal
  • Similar question: [Why can I pass 1 as a short, but not the int variable i?](http://stackoverflow.com/questions/11432508/why-can-i-pass-1-as-a-short-but-not-the-int-variable-i) – CodesInChaos Feb 18 '15 at 10:28

2 Answers2

5

Because when you assign a literal(constant value) compiler can prove the value fits in byte. When you assign a variable it can't.

If you assign a constant compiler is more than happy to compile because it can confirm that value is within the range of (0 - 255) which is the valid range for byte.

For example the following code compiles without any problem.

const int i = 123;
byte b = i; 
Sriram Sakthivel
  • 72,067
  • 7
  • 111
  • 189
0

The accepted answer is not quite correct.

In the second example, of course the compiler could prove that the value will fit, using simple static analysis. It's not allowed to, by the language specification.

It's trivial for a compiler such as the IL Jitter to prove this, and it does on many occasions. The C# compiler cannot accept this because it is against the specification.

The example given in that answer, is allowed because the spec allows it, not just because there is proof.

const int i = 123;
byte b = i; 

Let's take a look at the spec, ECMA-334 section §11.2.10 (you may find microsoft.com easier to navigate)

11.2.10 Implicit constant expression conversions

An implicit constant expression conversion permits the following conversions:

  • A constant-expression(§12.20) 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.

Let's take a look at §12.20 at what a constant-expression is defined as:

Constant expressions

A constant_expression is an expression that can be fully evaluated at compile-time.

A constant expression must be the null literal or a value with one of the following types: sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool, object, string, or any enumeration type. Only the following constructs are permitted in constant expressions:

  • Literals (including the null literal).
  • References to const members of class and struct types.
  • References to members of enumeration types.
  • References to const parameters or local variables
  • Parenthesized sub-expressions, which are themselves constant expressions.
  • Cast expressions, provided the target type is one of the types listed above.
  • checked and unchecked expressions
  • Default value expressions
  • Nameof expressions
  • The predefined +, -, !, and ~ unary operators.
  • The predefined +, -, *, /, %, <<, >>, &, |, ^, &&, ||, ==, !=, <, >, <=, and >= binary operators, provided each operand is of a type listed above.
  • The ?: conditional operator.

So, going back to the first example in the quesiton

byte b = 123;

The value 123 is a literal integer, which is a constant expression, and fits a byte therefore it can be implicitly converted into byte.

Next,

int i = 123;
byte b = i;

Here the value i is not a constant expression, therefore it cannot be implicitly converted to byte. There is no way for the compiler to allow this, because the spec disallows it.

Finally the example in the other answer

const int i = 123;
byte b = i; 

Here, i is a constant expression (because it is a reference to a const), whose value is known to fit into a byte, hence it is allowed by the spec.

Charlieface
  • 52,284
  • 6
  • 19
  • 43
  • `In the second example, of course the compiler could prove that the value will fit, using simple static analysis.` It also can't because of debuggers. Nothing stops you fiddling with the value in the debugger. So the status quo makes sense, in that regard. – mjwills Jul 05 '21 at 04:17
  • True, but in optimized Release build you might have thought it would do so. Do you think I have analyzed it correctly, generally? I know this is an old post, but it got duped recently – Charlieface Jul 05 '21 at 08:30
  • `True, but in optimized Release build you might have thought it would do so.` I don't think the Release build will give different warnings to the Debug build - although I could be wrong. Do I agree with the answer _overall_? Yes, I do. – mjwills Jul 05 '21 at 08:53