0

I stumbled across quite an interesting behavior and want to ask, if somebody can explain me why the following is not throwing an OverflowException in .NET languages (checked with .NET 6):

var f = (float)int.MaxValue;
Console.WriteLine(f); // 2.147484E+09, totally fine so far
var i = (int)f;
Console.WriteLine(i); // -2147483648, which is negative, no OverflowException

So, I understand that casting int.MaxValue to float will not be an exact representation of an integer and I understand too, that casting the result back to Int32 will most likely be not the same as what I had before, due to how floating point values are represented in memory. This is all fine.

But my naive expectation was, that a thought-through and beautiful language like C# would actually cause a System.OverflowException for the second conversion, which is apparently not the case.

In comparison, writing something like the following does already give us a compile time error, though basically doing the same (I know, I know, this is checked by the compiler and is not really related to the RT behavior):

int i = (int)(float)int.MaxValue;
// CS0221 Constant value '2.147484E+09' cannot be converted to a 'int' (use 'unchecked' syntax to override)

So my question is: Why is the .NET RT not throwing an exception here? Is this defined behavior according to the spec? I was not able to find anything in ECMA 334 which explains this discovery. On the contrary, check chapter "11.3.2 Explicit numeric conversions":

For a conversion from float or double to an integral type [...] the source operand is rounded towards zero to the nearest integral value. If this integral value is within the range of the destination type then this value is the result of the conversion. Otherwise, a System.OverflowException is thrown.

I'm sure that I cannot be the first person stumbling across such behavior, but I did not find anything on SO explaining me that and I don't believe that this is a RT bug which was never discovered in the history of .NET.

wobuntu
  • 422
  • 5
  • 12
  • You didn't read that section of the spec properly *"For a conversion from float or double to an integral type, the processing depends on the overflow- checking context (§12.7.14) in which the conversion takes place......"* – Charlieface Jun 19 '22 at 19:45
  • Does this answer your question? [No overflow exception for int in C#?](https://stackoverflow.com/questions/2056445/no-overflow-exception-for-int-in-c) – Charlieface Jun 19 '22 at 19:47
  • @Charlieface No, I've read that, but I was not aware that the default checking context for a project created with VS does not consider arithmetic overflows. As I wrote in the comment to SuRGeoNix answer, I was used to the default behavior of the old csproj file format, in which it was enabled for debug configurations by default. I did not notice that this changed with the template for the new format. Your link to the other question is helpful though, thanks. – wobuntu Jun 19 '22 at 20:12
  • Top answer of that question begins *"C# integer operations don’t throw exceptions upon overflow by default. You can achieve that via the project settings, or by making the calculation checked:"* which seems pretty clear to me. – Charlieface Jun 19 '22 at 20:15

1 Answers1

1

You will need to manually enable 'Check for arithmetic overflow' from project properties -> build -> advanced

SuRGeoNix
  • 482
  • 1
  • 3
  • 10
  • Well, this was a fast answer - thank you. Allowed me to google for more info. For anyone interested, the option in the .csproj is called `CheckForOverflowUnderflow` and looking at older projects on our repo server, it seems that it was by default set to `true` for debug and `false` in release configs of autogenerated .csproj files in the old csproj format. – wobuntu Jun 19 '22 at 18:07
  • ... or use a `checked {}` context, which is the same thing just local – Charlieface Jun 19 '22 at 19:43