Note: I posted this issue in C# repo as weel, but if they will not solve it at the compiler level, it can be solved at CoreFX leve, be defining overload math operators for these types:
Why have we to use cast to do basic math operations between bytes, short, and ushort? I think it will make things easier to define overload operators for those types.
For example:
short x = short.MaxValue;
ushort z =x + x;
this code will not even cause an overflow, but C# doesn't accept it. It only accepts:
short x = short.MaxValue;
ushort z =(ushort)(x + x);
@MohammadHamdyGhanem, there is no way to guarantee that (x + y) will return an unsigned value and allowing it to implicitly covert will likely result in even more bugs.
The C# compiler would also not respect these new custom operators, as it is hardcoded to emit raw IL instead of an op_Add call for these types. They would also not change the behavior due to it being a breaking change.
@tannergooding
there is no way to guarantee that (x + y) will return an unsigned value and allowing it to implicitly covert will likely result in even more bugs.
This is the same when you add two int that can generate an overflow. I onlt gave an example. C# is not resposible of the results, and should only throw an overflow exception.
This is an example tha is impossible to generate an overflow, yet C# refuses it:
byte x =2;
byte y = 1;
ushort z = x + y;
C# should fix this odd behaviour. I feel angery every time I get syntax error about this, and had to add extra casting!
C# should fix this odd behaviour. I feel angery every time I get syntax error about this, and had to add extra casting!
I would suggest opening a bug against the dotnet/csharplang repo.
@MohammadHamdyGhanem I am not sure which APIs exactly you suggest. Can you please describe the API and their usage?
Your first case of ushort = short + short without explicit cast is a very bad idea as @tannergooding mentioned -1 + 0 would silently become ushort.MaxValue.
ushort = byte + byte should not automatically cast either IMO, because it is not clear if the code wants to first cast to ushort and then add (255+255 = 510), or add with byte limitations (incl. underflow) and then cast to ushort (=254).
@karelz
C# Converts operands to int first, so the result is int, which makes a problem to implicitly cast it back to the desired type. So, ushort = byte + byte becomes ```ushort = int'''. This int is safe to be cast to ushort, so I can say: if neither of the two operands is int, it is safe to do implicit cast.
The ushort class can have these operator:
public static ushort implicit operator + (ushort x, ushort y)
=> ushort((int)x + (int)y);
so, ushort = byte + byte should call this operator. There is some work needed on the C# side, to decide to call ushort.OppAdd not byte.OpAdd based of the le4ft hand variable type. This woll make it behave as we expect. If any programmer have anything else in mind, he can do explicit casting.
This int is safe to be cast to ushort
This is not always true, and is therefore not safe to do by default.
The cast exists to ensure you understand the difference in behavior:
```C#
byte x = 255;
byte y = 255;
x += y;
byte z = (byte)(x + y);
```
The discussion is happening in https://github.com/dotnet/csharplang/issues/1624 - adding API to bypass C# features does not look like a good idea.
Most helpful comment
@MohammadHamdyGhanem, there is no way to guarantee that
(x + y)will return an unsigned value and allowing it to implicitly covert will likely result in even more bugs.