NSN
NSN

Reputation: 750

Evaluation of C# constant expression by VS.NET 2010

When I tried a sample expression in C# in Visual Studio

public int Test()
{
    if (10/2 == 5)
        throw new Exception();
    return 0;
}

When I keep the expression 10/2 == 5, the vs.net automatically throws a warning "Unreachable Code Detected".

If I change the expression 10/2 == 6, the IDE is happy? How does it happen?

Edited: Sorry for the incomplete question. It happens so instantly and happens even before compiling the code?

I have upvoted each of the replies and accepted the first answer on FIFO basis

Upvotes: 5

Views: 419

Answers (7)

Jeppe Stig Nielsen
Jeppe Stig Nielsen

Reputation: 61952

As others have said, the compiler can evaluate the expression 10 / 2 == 5 compile-time because it's a constant expression. It evaluates to true, therefore any code after the if scope is unreacable. If changed to false, the code inside the if is unreachable.

So now consider this code:

public int TestA() 
{ 
    if (10 / 2 == 5) 
        return 1; 
    return 0; 
} 

public int TestB() 
{ 
    if (10 / 2 == 6) 
        return 1; 
    return 0; 
} 

Both methods generate a warning about unreachable code!

The strange thing about the C# compiler is that if the unreachable code consists entirely of throw statements, then no warning will be issued about the unreachabiliy.

ADDITION: This Stack Overflow question is related

Upvotes: 4

Justin Pihony
Justin Pihony

Reputation: 67065

If you decompile this code, you will end up with:

public int Test()
{
     throw new Exception();
}

I believe that since these are constant values, that the math is done at compile time, so 10/2 is not really 10/2, but 5...so it becomes trivial for the compiler to realize that 5==5 is always going to be true. In fact, I believe these constants will then automatically be translated into true. The compiler's goal is to optimize out code that is ALWAYS going to repeat and run the processing of it at compile time, rather than running the same processing over and over.

So, basically, the compiler realizes that since the if is always true and the if results in a return (via a throw), so it optimizes out the code that it knows will never be executed. Thus, the decompiled code results in the above.

In fact, the opposite happens if you do the 10/2 == 6, which is "constantized" into 5 == 6, which is turned into false. Since the if will always be false, it optimizes out the if:

public int Test()
{
    int num = 0;
    return num;
}

Upvotes: 4

Roger Medeiros
Roger Medeiros

Reputation: 813

In fact he knows he will never come in return 0

He just warns that the entire code below the 10/2 == 5 will never be interpreted as 10/2 will always be 5.

In the same way:

if (true)
{
     ......
}
else 
{
  .....
}

Upvotes: 1

contactmatt
contactmatt

Reputation: 18600

The compiler is smart enough (this is a very simple check) and determines that return 0 will never be reached. This is because 10/2 == 5 will always be true. According to the compiler, the following expressions evaluate equally

if (10/2 == 5)

or

if true

The reason the compiler is able to determine this is because the numbers are not variable.

Upvotes: 1

Eamonn McEvoy
Eamonn McEvoy

Reputation: 8986

It is complaining that the line

return 0;

can never be reached. 10/2 is always equal to 5.

Upvotes: 3

Daniel
Daniel

Reputation: 2974

In the first case, the compiler processes the expression 10/2 == 5, which evaluates to true, so the exception is thrown and the return 0 statement is unreachable.

In the second case, 10/2 == 6 evaluates to false, so the return 0 statement is reachable as the exception is not thrown.

In response to your edit: Your code does not have to actually compile for the compiler to know that the line of code is unreachable. It is smart enough to know that 10/2 == 5 is ALWAYS true, regardless of any user input, meaning the exception will always be thrown.

Upvotes: 2

Thomas
Thomas

Reputation: 1321

if (10/2 == 5)

Will always return true, which means

throw new Exception();

Will always be executed, and

return 0;

Will never be reached

Upvotes: 9

Related Questions