C# under the covers III
So, you have some code that looks like this
private static bool Match(int item, int? target)
{
if (target.HasValue)
{
return item == target;
}
return false;
}
How many tests do you need to write to get 100% branch coverage?
If you answered "two -- one with a value, one without", you'd be as surprised as I was when I tried it.
It turns out that the implicit extraction of the value of the nullable value contains its own HasValue check, and the IL looks like
IL_0000: nop
IL_0001: ldarga.s target
IL_0003: call instance bool valuetype [mscorlib]System.Nullable\u00601::get_HasValue()
IL_0008: ldc.i4.0
IL_0009: ceq
IL_000b: stloc.1
IL_000c: ldloc.1
IL_000d: brtrue.s IL_002b
IL_000f: nop
IL_0010: ldarg.0
IL_0011: stloc.2
IL_0012: ldarg.1
IL_0013: stloc.3
IL_0014: ldloc.2
IL_0015: ldloca.s CS$0$0003
IL_0017: call instance !0 valuetype [mscorlib]System.Nullable\u00601::GetValueOrDefault()
IL_001c: bne.un.s IL_0027
IL_001e: ldloca.s CS$0$0003
IL_0020: call instance bool valuetype [mscorlib]System.Nullable\u00601::get_HasValue()
IL_0025: br.s IL_0028
IL_0027: ldc.i4.0
IL_0028: stloc.0
IL_0029: br.s IL_002f
IL_002b: ldc.i4.0
IL_002c: stloc.0
IL_002d: br.s IL_002f
IL_002f: ldloc.0
IL_0030: ret
Roughly, it goes "get a value, or the default, and test that; if not equal, accept that, otherwise only accept the equality if the nullable had a value."
If you write
private static bool Match(int item, int? target)
{
if (target.HasValue)
{
return item == target.Value;
}
return false;
}
then there is no compiler-generated branch for you to be caught by -- and it's probably slightly better coding practise, anyway.
No comments :
Post a Comment