Benchmark tests comparing ways of matching a variable against multiple possible options. As created for http://www.mrlacey.com/2017/10/optimizing-comparison-of-variable-with.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using BenchmarkDotNet.Attributes; | |
using BenchmarkDotNet.Running; | |
using System.Linq; | |
namespace IsOneOfBenchmarks | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
var summary = BenchmarkRunner.Run<Variations>(); | |
} | |
} | |
public class Variations | |
{ | |
private const MyEnum someVariable = MyEnum.Value3; | |
readonly MyEnum[] targetValues = { MyEnum.Value1, MyEnum.Value2, MyEnum.Value3, MyEnum.Value6 }; | |
[Benchmark] | |
public bool MultipleEquals() | |
{ | |
return someVariable == MyEnum.Value1 || someVariable == MyEnum.Value2 || | |
someVariable == MyEnum.Value3 || someVariable == MyEnum.Value6; | |
} | |
[Benchmark] | |
public bool IsOneOfObject() | |
{ | |
return someVariable.IsOneOf(MyEnum.Value1, MyEnum.Value2, MyEnum.Value3, MyEnum.Value6); | |
} | |
[Benchmark] | |
public bool IsOneOfObjectWithExistingArray() | |
{ | |
return someVariable.IsOneOf(targetValues); | |
} | |
[Benchmark] | |
public bool IsOneOfGeneric() | |
{ | |
return someVariable.IsOneOfGeneric<MyEnum>(MyEnum.Value1, MyEnum.Value2, MyEnum.Value3, MyEnum.Value6); | |
} | |
[Benchmark] | |
public bool IsOneOfGenericWithExistingArray() | |
{ | |
return someVariable.IsOneOfGeneric<MyEnum>(targetValues); | |
} | |
[Benchmark] | |
public bool IsOneOfMyEnum() | |
{ | |
return someVariable.IsOneOfMyEnum(MyEnum.Value1, MyEnum.Value2, MyEnum.Value3, MyEnum.Value6); | |
} | |
[Benchmark] | |
public bool IsOneOfMyEnumWithExistingArray() | |
{ | |
return someVariable.IsOneOfMyEnum(targetValues); | |
} | |
[Benchmark] | |
public bool IsOneOfMyEnumNoLinq() | |
{ | |
return someVariable.IsOneOfMyEnumNoLinq(MyEnum.Value1, MyEnum.Value2, MyEnum.Value3, MyEnum.Value6); | |
} | |
[Benchmark] | |
public bool IsOneOfMyEnumNoLinqWithExistingArray() | |
{ | |
return someVariable.IsOneOfMyEnumNoLinq(targetValues); | |
} | |
} | |
public static class ArrayExtensions | |
{ | |
public static bool IsOneOf(this object item, params object[] options) | |
{ | |
return options.Contains(item); | |
} | |
public static bool IsOneOfGeneric<T>(this T item, params T[] options) | |
{ | |
return options.Contains(item); | |
} | |
public static bool IsOneOfMyEnum(this MyEnum item, params MyEnum[] options) | |
{ | |
return options.Contains(item); | |
} | |
public static bool IsOneOfMyEnumNoLinq(this MyEnum item, params MyEnum[] options) | |
{ | |
for (var i = 0; i < options.Length; i++) | |
{ | |
if (item == options[0]) | |
{ | |
return true; | |
} | |
} | |
return false; | |
} | |
} | |
public enum MyEnum | |
{ | |
Value1, | |
Value2, | |
Value3, | |
Value4, | |
Value5, | |
Value6, | |
Value7, | |
Value8, | |
Value9, | |
Value0, | |
} | |
} |
Nice article!
I guess though that:
if (item == options[0]) { return true; }
should read:
if (item == options**[i]**) { return true; }
As a side note when it comes to enums, you should give this interesting article a read: https://blogs.msdn.microsoft.com/seteplia/2017/05/17/box-or-not-to-box-that-is-the-question/
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The results of my running these tests were
Conclusion
While using multiple equality checks is by far the fastest, I still think writing
is far less preferable to