Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why would I need to check for greater than Int32.MaxValue?

Tags:

c#

.net

I am using Visual Studio 2010 SP1 Ultimate on a c# class library project (.net 4) and I am curious about something...

Given this method:

public void DoSomethingBrilliant(int input)
{
    if (input == int.MaxValue)
        throw new ArgumentOutOfRangeException("input");

    input++;

    Console.WriteLine(input);
}

I get this warning from code analysis:

CA2233 : Microsoft.Usage : Correct the potential overflow in the operation 'input+1' in 'Test.DoSomethingBrilliant(int)'.

I thought to myself, that is a bit odd since I am checking that the input++ operation won't overflow by throwing that snazzy exception at the beginning but I changed it to this:

public void DoSomethingBrilliant(int input)
{
    if (input >= int.MaxValue)
        throw new ArgumentOutOfRangeException("input");

    input++;

    Console.WriteLine(input);
}

and sure enough the warning went away.

Now my little brain is all confused because given I am getting an int as an argument why would checking to see if it is greater than the maximum value allowed for an integer ever provide any value?

Then I went back to the original bit of code and switched to debug and it built without the warning! Curiouser and curioser...

I checked the differences between debug and release and found that if I tick the Optimize code option the warning from code analysis pops right back up.

So the optimization results in something that means I need to check for greater than int.MaxValue. Huh? Why? Am I being super dense? What has the optimization done that means I might get an int bigger than int.MaxValue passed into a method accepting an int?

Or, is this just a bug in the code analysis feature?

Update

Here is the IL for the "unoptimized" version (where the code analysis gets it right):

.method public hidebysig instance void  DoSomethingBrilliant(int32 input) cil managed
{
  // Code size       40 (0x28)
  .maxstack  2
  .locals init ([0] bool CS$4$0000)
  IL_0000:  nop
  IL_0001:  ldarg.1
  IL_0002:  ldc.i4     0x7fffffff
  IL_0007:  ceq
  IL_0009:  ldc.i4.0
  IL_000a:  ceq
  IL_000c:  stloc.0
  IL_000d:  ldloc.0
  IL_000e:  brtrue.s   IL_001b
  IL_0010:  ldstr      "input"
  IL_0015:  newobj     instance void [mscorlib]System.ArgumentOutOfRangeException::.ctor(string)
  IL_001a:  throw
  IL_001b:  ldarg.1
  IL_001c:  ldc.i4.1
  IL_001d:  add
  IL_001e:  starg.s    input
  IL_0020:  ldarg.1
  IL_0021:  call       void [mscorlib]System.Console::WriteLine(int32)
  IL_0026:  nop
  IL_0027:  ret
} // end of method Test::DoSomethingBrilliant

and here it is for the optimized version (where it gets it wrong):

.method public hidebysig instance void  DoSomethingBrilliant(int32 input) cil managed
{
  // Code size       31 (0x1f)
  .maxstack  8
  IL_0000:  ldarg.1
  IL_0001:  ldc.i4     0x7fffffff
  IL_0006:  bne.un.s   IL_0013
  IL_0008:  ldstr      "input"
  IL_000d:  newobj     instance void [mscorlib]System.ArgumentOutOfRangeException::.ctor(string)
  IL_0012:  throw
  IL_0013:  ldarg.1
  IL_0014:  ldc.i4.1
  IL_0015:  add
  IL_0016:  starg.s    input
  IL_0018:  ldarg.1
  IL_0019:  call       void [mscorlib]System.Console::WriteLine(int32)
  IL_001e:  ret
} // end of method Test::DoSomethingBrilliant

I see a bunch of extra calls before the throw operation but I am going to be honest - I have no idea what they do!

like image 723
kmp Avatar asked Jun 27 '12 12:06

kmp


People also ask

What is Int32 MinValue?

The MinValue property or Field of Int32 Struct is used to represent the minimum possible value of Int32. The value of this field is constant means that a user cannot change the value of this field. The value of this field is -2,147,483,648. Its hexadecimal value is 0x80000000.

What is Int32 MaxValue?

The value of this constant is 2,147,483,647; that is, hexadecimal 0x7FFFFFFF.

What is bigger than Int32?

Int16 is 16 bit, int32 is 32 bit and int64 is 64 bit.

What is value & int MaxValue in C#?

Represents the largest possible value of an Int32. This field is constant. public: int MaxValue = 2147483647; C# Copy.


1 Answers

Or, is this just a bug in the code analysis feature?

Looks like it. Not terribly surprising, to be honest - getting this sort of code analysis to be perfect is mightily tricky. Given that any particular int cannot be greater than int.MaxValue, >= and == are definitely equivalent.

like image 191
Jon Skeet Avatar answered Sep 28 '22 02:09

Jon Skeet