In case someone wonders about the impact of boxing performance in the structure of the Nullable object (to avoid double checking from is and casts), there is some minor overhead.
tl; dr : use is and produce in this script.
struct Foo : IEquatable<Foo> { public int a, b; public Foo(int a, int b) { this.a = a; this.b = b; } public override bool Equals(object obj) { #if BOXING var obj_ = obj as Foo?; return obj_ != null && Equals(obj_.Value); #elif DOUBLECHECK return obj is Foo && Equals((Foo)obj); #elif MAGIC ? #endif } public bool Equals(Foo other) { return a == other.a && b == other.b; } } class Program { static void Main(string[] args) { RunBenchmark(new Foo(42, 43), new Foo(42, 43)); RunBenchmark(new Foo(42, 43), new Foo(43, 44)); } static void RunBenchmark(object x, object y) { var sw = Stopwatch.StartNew(); for (var i = 0; i < 100000000; i++) x.Equals(y); sw.Stop(); Console.WriteLine(sw.ElapsedMilliseconds); } }
Results:
BOXING EQ 8012 7973 7981 8000 NEQ 7929 7715 7906 7888 DOUBLECHECK EQ 3654 3650 3638 3605 NEQ 3310 3301 3319 3297
Warning. This test can be ruined in many ways, although I made sure that the test code itself was not optimized in an odd way.
Looking at IL, the double check method compiles a little cleaner.
Boxing IL:
.method public hidebysig virtual instance bool Equals ( object obj ) cil managed {
Double check IL:
.method public hidebysig virtual instance bool Equals ( object obj ) cil managed {
Details to Roman Rainer for the fact that he noticed a mistake that really did not make me look good.
tne 02 Feb '15 at 15:46 2015-02-02 15:46
source share