views:

41

answers:

3

After writing code that can be boiled down to the following:

var size=-1;
var arr=new byte[size];

I was surprised that it threw an OverflowException. The docs for OverflowException state:

The exception that is thrown when an arithmetic, casting, or conversion operation in a checked context results in an overflow.

I couldn't see how providing a negative size for and array length fits into the description given for this exception, so delved a little deeper and found that this is indeed the specified behaviour:

The computed values for the dimension lengths are validated as follows. If one or more of the values are less than zero, a System.OverflowException is thrown and no further steps are executed.

I wonder why OverflowException was chosen. It's pretty misleading if you ask me. It cost me at least 5 minutes of investigation (not counting my musings here). Can anyone shed any light on this (to my thinking) peculiar design decision?

+1  A: 

It might be because that size is an unsigned int. It stores -1 in two's complement, which when looked at as a unsigned int, is the maximum positive integer that can be stored. If this number is bigger than the possible size of an array, it will overflow.

Warning: this is pure speculation.

xxpor
Array sizes, in .NET, are stored as Int32, not unsigned. I believe this was done in order to keep arrays CLS compliant.
Reed Copsey
I was originally thinking along these lines, but the spec is quite specific that it is negative size that causes this Exception.
spender
+2  A: 

OverflowException, in the documentation, basically defines an overflow as something that:

produces a result that is outside the range of the data type

In this case, negative values are outside of the valid range for an array size (or really, any size).

I could see the argument that ArgumentOutOfRangeException might be, in some ways, better - however, there is no argument involved in an array definition (as its not a method), so it, too, would not be a perfect choice.

Reed Copsey
+2  A: 

This is almost certainly an optimization. The .NET framework code is pretty religious about checking arguments to let the programmer fall in the pit of success. But that doesn't come for free. The cost is fairly minuscule, many class methods take lots more machine cycles then is spent on the checking.

But arrays are special. They are the very core data structure in the framework. Almost every collection class is built on top of them. Any overhead put in the Array class directly impacts the efficiency of a lot of code that sits on top of it. Avoiding the check is okay, it gets implicitly checked anyway when the internal code needs to cast the value to unsigned. And it is very rare that it trips. So checking it twice is not quite worth the better exception message.

Hans Passant