Here's a surprise, range operator is beaten by a large set of serial cases statements!
In the below code example which validates a drive letter, by
using System.Runtime.CompilerServices;
you can adorn the case-statement method to be compiled with
[MethodImplAttribute(MethodImplOptions.AggressiveOptimization )] and/or
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
to surprising results. I was surprised by v6. v5 and v6 win on alternative runs.
Full documentation here - https://docs.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.methodimploptions
Source Code
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
public static class Program
{
//Fri 30-Oct-20 2:17pm metadataconsulting.ca
//https://metadataconsulting.blogspot.com/2020/10/C-NET-Validate-Drive-Letter-with-compiler-optimization-aggressive-in-lining-for-large-fall-through-case-statements.html
//-> this method does not exist on the interwebs, trivial?
//-> fun with compiler switches to optimize case statements
public static bool isValidDriveLetter(this string drivewithcolon)
{
if (drivewithcolon.Length == 2 && drivewithcolon[1] == ':')
{
drivewithcolon = drivewithcolon.ToUpper();
// this is surprisingly faster than the equivalent if statement
switch (drivewithcolon[0])
{
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'H':
case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
case 'Q':
case 'R':
case 'S':
case 'T':
case 'U':
case 'V':
case 'W':
case 'X':
case 'Y':
case 'Z':
return true;
default:
return false;
}
}
else
return false;
}
//range operator
public static bool isValidDriveLetterV2(this string drivewithcolon)
{
if (drivewithcolon.Length == 2 && drivewithcolon[1] == ':')
{
drivewithcolon = drivewithcolon.ToUpper();
if (drivewithcolon[0] >= 'A' && drivewithcolon[0] <= 'Z')
return true;
else
return false;
}
else
return false;
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
public static bool isValidDriveLetterV3(this string drivewithcolon)
{
if (drivewithcolon.Length == 2 && drivewithcolon[1] == ':')
{
drivewithcolon = drivewithcolon.ToUpper();
// this is surprisingly faster than the equivalent if statement
switch (drivewithcolon[0])
{
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'H':
case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
case 'Q':
case 'R':
case 'S':
case 'T':
case 'U':
case 'V':
case 'W':
case 'X':
case 'Y':
case 'Z':
return true;
default:
return false;
}
}
else
return false;
}
[MethodImplAttribute(MethodImplOptions.AggressiveOptimization)]
public static bool isValidDriveLetterV4(this string drivewithcolon)
{
if (drivewithcolon.Length == 2 && drivewithcolon[1] == ':')
{
drivewithcolon = drivewithcolon.ToUpper();
// this is surprisingly faster than the equivalent if statement
switch (drivewithcolon[0])
{
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'H':
case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
case 'Q':
case 'R':
case 'S':
case 'T':
case 'U':
case 'V':
case 'W':
case 'X':
case 'Y':
case 'Z':
return true;
default:
return false;
}
}
else
return false;
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static bool isValidDriveLetterV5(this string drivewithcolon)
{
if (drivewithcolon.Length == 2 && drivewithcolon[1] == ':')
{
drivewithcolon = drivewithcolon.ToUpper();
// this is surprisingly faster than the equivalent if statement
switch (drivewithcolon[0])
{
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'H':
case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
case 'Q':
case 'R':
case 'S':
case 'T':
case 'U':
case 'V':
case 'W':
case 'X':
case 'Y':
case 'Z':
return true;
default:
return false;
}
}
else
return false;
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static bool isValidDriveLetterV6(this string drivewithcolon)
{
if (drivewithcolon.Length == 2 && drivewithcolon[1] == ':')
{
drivewithcolon = drivewithcolon.ToUpper();
if (drivewithcolon[0] >= 'A' && drivewithcolon[0] <= 'Z')
return true;
else
return false;
}
else
return false;
}
public static void Main()
{
bool v1,v2,v3,v4,v5,v6 = false;
Stopwatch sw = new Stopwatch();
sw.Start();
v1= "Z:".isValidDriveLetter();
sw.Stop();
Console.WriteLine("is Z: valid drive letter ?{0}, v1 in {1} ticks.",v1.ToString(), sw.ElapsedTicks);
sw.Reset();
sw.Start();
v2= "Z:".isValidDriveLetterV2();
sw.Stop();
Console.WriteLine("is Z: valid drive letter ?{0}, v2 in {1} ticks.",v2.ToString(), sw.ElapsedTicks);
sw.Reset();
sw.Start();
v3= "Z:".isValidDriveLetterV3();
sw.Stop();
Console.WriteLine("is Z: valid drive letter ?{0}, v3 in {1} ticks.",v3.ToString(), sw.ElapsedTicks);
sw.Reset();
sw.Start();
v4= "Z:".isValidDriveLetterV4();
sw.Stop();
Console.WriteLine("is Z: valid drive letter ?{0}, v4 in {1} ticks.",v4.ToString(), sw.ElapsedTicks);
sw.Reset();
sw.Start();
v5= "Z:".isValidDriveLetterV5();
sw.Stop();
Console.WriteLine("is Z: valid drive letter ?{0}, v5 in {1} ticks.",v5.ToString(), sw.ElapsedTicks);
sw.Reset();
sw.Start();
v6= "Z:".isValidDriveLetterV6();
sw.Stop();
Console.WriteLine("is Z: valid drive letter ?{0}, v6 in {1} ticks.",v6.ToString(), sw.ElapsedTicks);
}
}