5

I was testing something out using LinqPad and was surprised that the following code did not produce an exception:

ulong lSmallValue = 5;
ulong lBigValue = 10;

ulong lDifference = lSmallValue - lBigValue;

Console.WriteLine(lDifference);
Console.WriteLine((long)lDifference);

This produces the following output:

18446744073709551611
-5

Fortunately, I was hoping for this behavior, but I was under the assumption that this would cause an OverflowException to be thrown.

From System.OverflowException:

An OverflowException is thrown at run time under the following conditions:

  • An arithmetic operation produces a result that is outside the range of the data type returned by the operation.
  • A casting or conversion operation attempts to perform a narrowing conversion, and the value of the source data type is outside the range of the target data type.

Why doesn't the operation lSmallValue - lBigValue fall into the first category?

Anthony
  • 9,451
  • 9
  • 45
  • 72
  • Probably it is _not_ outside the range; the `ulong` still has enough _bits_ to hold the values of your operation (although it is interpreted different to what you expect). – Uwe Keim Sep 24 '12 at 19:25

2 Answers2

11

CLR will not throw the Overflow exception by default. Unless you're using the "checked" keyword.

http://msdn.microsoft.com/en-us/library/74b4xzyw%28v=vs.71%29.aspx

UPD: Actually, I do recommend the "CLR via C#" by Jeffrey Richter - he makes these things so much more transparent. My favorite book about the CLR and C# fundamentals.

Mikhail
  • 898
  • 7
  • 21
  • 2
    This does in-fact cause the exception to be thrown. Thanks, I've never run into the `checked` keyword before. – Anthony Sep 24 '12 at 19:28
0

"For the arithmetic, casting, or conversion operation to throw an OverflowException, the operation must occur in a checked context."

The OverflowException will be called as soon as you put your code within a checked block.

ulong lSmallValue = 5;
ulong lBigValue = 10;
checked {
try {
    ulong lDifference = lSmallValue - lBigValue;
}
catch (OverflowException) {
    Console.WriteLine("Exception caught");
}}
Mark
  • 6,033
  • 1
  • 19
  • 14
  • 1
    This is wrong, if I wrap it in a try..catch block in LinqPad still no exception is thrown. – Anthony Sep 24 '12 at 19:26
  • 1
    "Checked" in this case has nothing to do with try/catch. There is a `checked { }` block, iirc, that turns on overflow checking. – cHao Sep 24 '12 at 19:27
  • 1
    I don't think that this is a correct answer - try catch doesn't make any sense there. You need to use the "cehcked" keyword. See my response lower – Mikhail Sep 24 '12 at 19:27
  • -1 This is wrong. Checked context has nothing to do with try/catch and everything to do with being run within a `checked` block. `unchecked` context is the default. – Chris Hannon Sep 24 '12 at 19:28
  • I'm not getting any exceptions when that code is inside a try..catch block. – Gromer Sep 24 '12 at 19:29
  • Oops, of course. The checked context is required. I adapted the text. – Mark Sep 24 '12 at 19:30