int int1;
byte byte1;
unchecked
{
int1 = 2147483647 + 10; //ok
byte1 = 200+100; //error
}
1)Only difference between int1 and byte1 overflows is that the latter happened during narrowing conversion attempt, but the end result ( overflowing ) is the same, so why doesn’t compiler also ignore byte1 overflow ( I’m aware that compiler allows constant expressions of type int to be converted to smaller type only if the value is within the range of the target type, but I would expect compiler to ignore such overflows if they happened inside unchecked context)?
2) Aren’t checked and unchecked operators/statements only “active” during runtime (ie don’t they establish overflow checking context only during runtime)? If so, then in above code compiler should also report an error when int1 overflowed, since constant expressions are inspected during compile time, and at that point unchecked statement is not yet “active” and thus it won’t yet establish unchecked overflow context?1
thank you
It’s best not to think of the unchecked or checked contexts (whether from compilation settings or the
uncheckedandcheckedkeywords) as affecting whether or not something errors. Rather it’s better to think of it as changing the meaning.In an checked context,
x + y(where x and y are bothints) means “take the integral number x (in the range [-2147483648–+2147483647]) and the number y (in the range [-2147483648–+2147483647]), add them, and return the number (in the range [-2147483648–+2147483647]) obtained by that addition”.In other words, it means much the same thing as we explain to young children when we’re teaching them arithmetic, but with some range limitations applied, mostly as an implementation detail. If the code can’t do what we ask, because it can’t keep to that range limitation, then we get an exception. Just like we get an exception when we try to read a file that doesn’t exist or anything else that isn’t actually possible.
In an unchecked context
x + ymeans “treat x and y as a pair of 32-bit twos-complement binary numbers, and perform binary addition on them, ignoring any overflow on the final bit, and return the number).Now, if you have a two-complement machine, then the only practical difference between this and the most natural implementation of the checked form is that we don’t get an exception in the case of overflow.
However, there’s both a technical and conceptual difference difference beyond this.
The technical difference is that if a machine where not twos-complement, it would have to fake it to provide the required behaviour (in particular the range of
intis not that of a 32-bit ones-complement integer).The conceptual difference is more important. When you are doing unchecked addition, then for 2000000000 + 2000000000 the result of -294967296 is the right answer. It’s not a failure condition, like the exception we get if we do the same addition checked, it’s not a broken attempt to store 4000000000 in a 32-bit twos complement binary number, it is the precisely correct result we want.
We don’t want this is we have two boxes full of 2000000000 marbles each and try to add up all the marbles. We do want this when addition is used in certain bit-twiddling operations or where losing information is part of the intent (e.g. mult-and-add hashing methods).
The difference between checked and unchecked is not about safety vs speed, but about having two different meanings, albeit meanings that overlap at the ranges where overflow doesn’t happen.
Now, considering all of that, let’s consider what the following mean:
The first means, “take 100, add 100 to it, and put the result into the byte b0, which it will happily fit into”. The second means “take 100, add 100 to it, and then force the result into b1 whether it wants to fit or not”.
Being checked or unchecked can’t change the way the first works. Whatever way addition is worked out, either we can state “it will happily fit into the variable” or we cannot.
Being checked or unchecked those though affect the latter, in changing how overflow is treated in the forcible fitting entailed by the explicit conversion. Hence doubling the values to:
Will have the following results:
In particular, note the difference between
byte b = 100 + 100;which assigns a literal byte andbyte b = x + y‘, which is not allowed as even if x and y are bytes, the result of their addition isint. There is no overflow involved here, but it does show the other side of why your byte assignment isn’t allowed.