0

I'm new to C#.

Firstly, may I ask if int is the default type for integers in C#? In other words, are literals of whole number being treated as int in C#?

If so, since we can always declare, say, a byte as follows:

byte b = 1;

may I ask if there is an implicit type conversion happening during this initialisation (my guess: literal 1 is being treated as int first and then being converted to byte)?

If my guess above is correct, may I ask why we are allowed to implicitly convert int to byte using literal as above while we cannot do that when the literal is replaced by a variable of type int (say for example as follows)?

int a = 1;
byte c = a; // error

Moreover, I found that for constants:

const int d = 1;
byte f = d; // no error
const long g = 1;
int i = g; // error
byte h = g; //error

Could anyone please give more explanations on these?

I'm asking this since it gives me a feeling of inconsistency.

Many thanks

J-A-S
  • 368
  • 1
  • 8
  • [Integral numeric types (C# reference)](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/integral-numeric-types#integer-literals): *"If the determined type of an integer literal is int and the value represented by the literal is within the range of the destination type, the value can be implicitly converted to sbyte, byte, short, ushort, uint, ulong, nint or nuint"* The behavior is specific to literals to eliminate the need to cast them explicitly in common cases. – madreflection Jul 03 '21 at 00:44
  • yes, you're right. For consistency, think that's it's easy for the compiler to "select" the correct type for litterals at compile time. In the case of variables, it might be simple in your example, but _in general_ (variables passed between objects, maybe from an external already compiled library), it's a much more tough guess. Let's say simply that, by design, the creators of the language decided not to permit this auto cast in the case of variable. The exact reason is probably known only by them, but I think i gave you a possible one. – Pac0 Jul 03 '21 at 00:44
  • @madreflection Thank you very much for your reference that helps a lot, could you also please have a look at the constants part of this question? – J-A-S Jul 03 '21 at 00:58
  • 1
    I think it is to do with data type _and_ value. The example you gave where `const int` can be assigned to `byte` but not non-const, it would be because `const` is different in C# than in C++. Compiler knows for sure what value it is going to be (not same in C++). If you change value from 1 to 12334, conversion won't happen and you will get an error. –  Jul 03 '21 at 00:59
  • @vish Sorry I'm not sure if I understand you correctly, do you mean the C# compiler knows the value of a constant while C++ compiler may not? I still don't understand why in that case const long cannot be assigned to int/short/byte? – J-A-S Jul 03 '21 at 01:10
  • @Pac0 Thank you very much for your patient reply :) may I further ask what happens related to the constants above? – J-A-S Jul 03 '21 at 01:11
  • @J-A-S, In C++ following is possible: ` const int i = 0; int &x = const_cast(i); x = 10; ` As for why not const long, it is because of what @madreflection stated from standard "If the determined type of an integer literal is int...". –  Jul 03 '21 at 01:23

1 Answers1

3

are literals of whole number being treated as int in C#?

Not necessarily. Integer literals can have the type int, uint, long and ulong, depending on what suffix (U and/or L) it has.

Also:

If the literal has no suffix, it has the first of these types in which its value can be represented: int, uint, long, ulong.

So if the value can fit an int, it will have the type int. If it can't fit an int but can a uint, then it will have the type uint, and so on.

may I ask if there is an implicit type conversion happening during this initialisation?

may I ask why we are allowed to implicitly convert int to byte using literal as above while we cannot do that when the literal is replaced by a variable of type int?

In both of these lines,

byte b = 1;
byte f = d;

the same conversion is performed - an implicit constant expression conversion.

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.

Both the literal 1 and d are constant expressions of type int.

a doesn't work because it is a variable, clearly not a constant, so not a constant expression.

g doesn't work because it is a constant expression of type long, and implicit constant expression conversions only works on ints.

Sweeper
  • 213,210
  • 22
  • 193
  • 313