Reputation: 48736
I have the following function:
public string MyPhrase(int val)
{
if ((val %3 == 0) && (val % 6 == 0))
return "Fizz Bang";
if (val % 3 == 0)
return "Fizz";
if (val % 6 == 0)
return "Bang";
return "";
}
After compiling this and viewing it with IlDasm, I get this output:
IL_0000: ldarg.1
IL_0001: ldc.i4.3
IL_0002: rem
IL_0003: brtrue.s IL_0010
IL_0005: ldarg.1
IL_0006: ldc.i4.6
IL_0007: rem
IL_0008: brtrue.s IL_0010
IL_000a: ldstr "Fizz Bang"
IL_000f: ret
IL_0010: ldarg.1
IL_0011: ldc.i4.3
IL_0012: rem
IL_0013: brtrue.s IL_001b
IL_0015: ldstr "Fizz"
IL_001a: ret
IL_001b: ldarg.1
IL_001c: ldc.i4.6
IL_001d: rem
IL_001e: brtrue.s IL_0026
IL_0020: ldstr "Bang"
IL_0025: ret
IL_0026: ldstr ""
IL_002b: ret
From looking at this page, brtrue
will branch if true. What's confusing me is the line IL_0003
. Its saying that it should branch to line IL_0010
if its true. In my C# code though, I am using an &&
to compare two expressions before my program flow should jump to the next if
. It seems backwards. From the MSIL code posted, it seems like its checking to see if my operation is true and if it is, its jumping to my next if
block, which would be logically wrong. Can someone explain what I'm missing?
Upvotes: 2
Views: 574
Reputation: 3698
brtrue.s transfers control to the given target if the value on the stack is non-zero.
so, In your IL code IL_0003
is tranfers control to IL_0010
. means (val % 3 == 0) condition return false. you used &&
in first if condition if ((val %3 == 0) && (val % 6 == 0))
so, on first condition (val % 3 == 0)
return false, second condition will not check
IL_0005: ldarg.1
IL_0006: ldc.i4.6
IL_0007: rem
IL_0008: brtrue.s IL_0010
and control transfer to IL_0010
IL_0010: ldarg.1
IL_0011: ldc.i4.3
IL_0012: rem
IL_0013: brtrue.s IL_001b
check out this for more information: http://weblogs.asp.net/kennykerr/archive/2004/09/23/introduction-to-msil-part-6-common-language-constructs.aspx
Upvotes: 1
Reputation: 942197
This is a side-effect of short circuit evaluation for the && operator. Which promises that the right-hand expression of the operator does not get evaluated if the left-hand side is false. So you see it skip the val % 6 == 0 expression and the return "Fizz Bang" statement if the REM opcode returns a non-zero result.
Upvotes: 4
Reputation: 29000
This blok load arguments data from Stack, before begin comparing
So it's normal to jump to this section of loading data
IL_0010: ldarg.1
IL_0011: ldc.i4.3
...
Upvotes: 0