home comics writing pictures archive about

2017-06-24 - In IL: VB Grade Analyser (Select)

In IL

The Visual Basic .NET Select statement is a lot like the C# switch statement. The two have similar syntax and are used for similar purposes but the VB version provides more options. For example the C# switch statement requires exact values where as the VB Select statement allows you to enter conditionals.

Let's start by looking at a Select statement which performs the same operations as the switch statement from part 10.

Module1.vb
Module Module1
Sub Main()
Dim grade As Char = "B"c
Dim needToImprove as Boolean = False
Select Case grade
Case "A"c
Console.WriteLine("Your grade is excellent")
needToImprove = False
Case "B"c
Console.WriteLine("Your grade is good")
needToImprove = False
Case "C"c
Console.WriteLine("Your grade is OK")
needToImprove = True
Case "D"c
Console.WriteLine("Your grade is acceptable")
needToImprove = True
Case Else
Console.WriteLine("You failed")
needToImprove = True
End Select
If needToImprove Then
Console.WriteLine("You can do better")
End If
End Sub
End Module
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

As you can see the syntax of the Select statement is very much like that of the switch statement. Now let's look at the generated IL.

Main
.method public static void Main() cil managed
{
.entrypoint
.custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
// Code size 114 (0x72)
.maxstack 2
.locals init ([0] char grade,
[1] bool needToImprove)
IL_0000: ldc.i4.s 66
IL_0002: stloc.0
IL_0003: ldc.i4.0
IL_0004: stloc.1
IL_0005: ldloc.0
IL_0006: ldc.i4.s 65
IL_0008: sub
IL_0009: switch (
IL_0020,
IL_002e,
IL_003c,
IL_004a)
IL_001e: br.s IL_0058
IL_0020: ldstr "Your grade is excellent"
IL_0025: call void [mscorlib]System.Console::WriteLine(string)
IL_002a: ldc.i4.0
IL_002b: stloc.1
IL_002c: br.s IL_0064
IL_002e: ldstr "Your grade is good"
IL_0033: call void [mscorlib]System.Console::WriteLine(string)
IL_0038: ldc.i4.0
IL_0039: stloc.1
IL_003a: br.s IL_0064
IL_003c: ldstr "Your grade is OK"
IL_0041: call void [mscorlib]System.Console::WriteLine(string)
IL_0046: ldc.i4.1
IL_0047: stloc.1
IL_0048: br.s IL_0064
IL_004a: ldstr "Your grade is acceptable"
IL_004f: call void [mscorlib]System.Console::WriteLine(string)
IL_0054: ldc.i4.1
IL_0055: stloc.1
IL_0056: br.s IL_0064
IL_0058: ldstr "You failed"
IL_005d: call void [mscorlib]System.Console::WriteLine(string)
IL_0062: ldc.i4.1
IL_0063: stloc.1
IL_0064: ldloc.1
IL_0065: brfalse.s IL_0071
IL_0067: ldstr "You can do better"
IL_006c: call void [mscorlib]System.Console::WriteLine(string)
IL_0071: ret
} // end of method Module1::Main
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561

The generated IL for the Select statement looks almost identical to that generated for the switch statement. This is to be expected since the two programs are doing the same thing.

Now we're going to change the program to take numerical ranges instead of characters.

Module1.vb
Module Module1
Sub Main()
Dim needToImprove As Boolean = False
Dim grade As Integer = 75
Select Case grade
Case > 90
Console.WriteLine("Your grade is excellent")
needToImprove = False
Case > 80
Console.WriteLine("Your grade is good")
needToImprove = False
Case > 70
Console.WriteLine("Your grade is OK")
needToImprove = True
Case > 60
Console.WriteLine("Your grade is acceptable")
needToImprove = True
Case > 50
Console.WriteLine("You passed")
needToImprove = True
Case Else
Console.WriteLine("You failed")
needToImprove = True
End Select
If needToImprove Then
Console.WriteLine("You can do better")
End If
End Sub
End Module
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

This program isn't that different from the first one except for the variable being checked and the cases. If we compile this into IL however we see it's quite a bit different.

Main
.method public static void Main() cil managed
{
.entrypoint
.custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )
// Code size 126 (0x7e)
.maxstack 2
.locals init ([0] bool needToImprove,
[1] int32 V_1)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: ldc.i4.s 75
IL_0004: stloc.1
IL_0005: ldloc.1
IL_0006: ldc.i4.s 90
IL_0008: ble.s IL_0018
IL_000a: ldstr "Your grade is excellent"
IL_000f: call void [mscorlib]System.Console::WriteLine(string)
IL_0014: ldc.i4.0
IL_0015: stloc.0
IL_0016: br.s IL_0070
IL_0018: ldloc.1
IL_0019: ldc.i4.s 80
IL_001b: ble.s IL_002b
IL_001d: ldstr "Your grade is good"
IL_0022: call void [mscorlib]System.Console::WriteLine(string)
IL_0027: ldc.i4.0
IL_0028: stloc.0
IL_0029: br.s IL_0070
IL_002b: ldloc.1
IL_002c: ldc.i4.s 70
IL_002e: ble.s IL_003e
IL_0030: ldstr "Your grade is OK"
IL_0035: call void [mscorlib]System.Console::WriteLine(string)
IL_003a: ldc.i4.1
IL_003b: stloc.0
IL_003c: br.s IL_0070
IL_003e: ldloc.1
IL_003f: ldc.i4.s 60
IL_0041: ble.s IL_0051
IL_0043: ldstr "Your grade is acceptable"
IL_0048: call void [mscorlib]System.Console::WriteLine(string)
IL_004d: ldc.i4.1
IL_004e: stloc.0
IL_004f: br.s IL_0070
IL_0051: ldloc.1
IL_0052: ldc.i4.s 50
IL_0054: ble.s IL_0064
IL_0056: ldstr "You passed"
IL_005b: call void [mscorlib]System.Console::WriteLine(string)
IL_0060: ldc.i4.1
IL_0061: stloc.0
IL_0062: br.s IL_0070
IL_0064: ldstr "You failed"
IL_0069: call void [mscorlib]System.Console::WriteLine(string)
IL_006e: ldc.i4.1
IL_006f: stloc.0
IL_0070: ldloc.0
IL_0071: brfalse.s IL_007d
IL_0073: ldstr "You can do better"
IL_0078: call void [mscorlib]System.Console::WriteLine(string)
IL_007d: ret
} // end of method Module1::Main
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577

Gone is the switch instruction and the individual cases. Now we have a series of jumps. If you go back a few parts this actually looks like an If-ElseIf ladder. Which is how we would likely write this kind of code in C#. This goes back to what I've said before which is that the compiler is there to help you and make things easier. You don't need a Select statement which can accept ranges because you can already do that using If Else statements and the generated code will be the same in either case. The benefit of the Select statement accepting ranges is not in what it allows you to do but in how it allows you to express what you want to do.

Next time we are going to start looking at loops.

Comments: