Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Instead of error, why don't both operands get promoted to float or double?

Tags:

c#

1) If one operand is of type ulong, while the other operand is of type sbyte/short/int/long, then compile-time error occurs. I fail to see the logic in this. Thus, why would it be bad idea for both operands to instead be promoted to type double or float?

        long L = 100;
        ulong UL = 1000;
        double d = L + UL; // error saying + operator can't be applied
                              to operands of type ulong and long

b) Compiler implicitly converts int literal into byte type and assigns resulting value to b:

byte b = 1;

But if we try to assign a literal of type ulong to type long(or to types int, byte etc), then compiler reports an error:

long L = 1000UL;

I would think compiler would be able to figure out whether result of constant expression could fit into variable of type long?!

thank you

like image 987
flockofcode Avatar asked Jul 10 '10 19:07

flockofcode


4 Answers

To answer the question marked (1) -- adding signed and unsigned longs is probably a mistake. If the intention of the developer is to overflow into inexact arithmetic in this scenario then that's something they should do explicitly, by casting both arguments to double. Doing so implicitly is hiding mistakes more often than it is doing the right thing.

To answer the question marked (b) -- of course the compiler could figure that out. Obviously it can because it does so for integer literals. But again, this is almost certainly an error. If your intention was to make that a signed long then why did you mark it as unsigned? This looks like a mistake. C# has been carefully designed so that it looks for weird patterns like this and calls your attention to them, rather than making a guess that you meant to say this weird thing and blazing on ahead as if everything were normal. The compiler is trying to encourage you to write sensible code; sensible code does not mix signed and unsigned types.

like image 59
Eric Lippert Avatar answered Nov 12 '22 22:11

Eric Lippert


Why should it?

Generally, the 2 types are incompatible because long is signed. You are only describing a special case.

For byte b = 1; 1 has no implicit type as such and can be coerced into byte

For long L = 1000UL; "1000UL" does have an explicit type and is incompatible and see my general case above.

Example from "ulong" on MSDN:

When an integer literal has no suffix, its type is the first of these types in which its value can be represented: int, uint, long, ulong.

and then

There is no implicit conversion from ulong to any integral type

On "long" in MSDN (my bold)

When an integer literal has no suffix, its type is the first of these types in which its value can be represented: int, uint, long, ulong.

It's quite common and logical and utterly predictable

like image 21
gbn Avatar answered Nov 12 '22 22:11

gbn


long l = 100;  
ulong ul = 1000;  
double d = l + ul;  // error 

Why would it be bad idea for both operands to instead be promoted to type double or float?

Which one? Floats? Or doubles? Or maybe decimals? Or longs? There's no way for the compiler to know what you are thinking. Also type information generally flows out of expressions not into them, so it can't use the target of the assignment to choose either.

The fix is to simply specify which type you want by casting one or both of the arguments to that type.

like image 2
Mark Byers Avatar answered Nov 12 '22 23:11

Mark Byers


The compiler doesn't consider what you do with the result when it determines the result type of an expression. The rules for how types are promoted in an expression only consider the values in the expression itself, not what you do with the value later on.

In the case where you assign the result to a variable, it could be possible to use that information, but consider a statement like this:

Console.Write(L + UL);

The Write method has overloads that take several different data types, which would make it rather complicated to decide how to use that information.

For example, there is an overload that takes a string, so one possible way to promote the types (and a good candidate as it doesn't lose any precision) would be to first convert both values to strings and then concatenate them, which is probably not the result that you were after.

like image 2
Guffa Avatar answered Nov 12 '22 23:11

Guffa