public void StaticFieldGetter1WorksWithBoxing()
        {
            var field = typeof(Garply).GetField(nameof(Garply.Baz));

            var getter = new StaticFieldGetter <IBaz>(field !);

            getter.Func.Target.Should().BeSameAs(getter);
            getter.Func.Method.Name.Should().Be(nameof(getter.GetValueReflection));
            getter.Func.Method.DeclaringType.Should().Be(typeof(StaticFieldGetter <IBaz>));

            using (var gc = new GCNoRegion(4194304))
            {
                var  reflectionTimer = Stopwatch.StartNew();
                IBaz reflectionValue = getter.GetValue();
                reflectionTimer.Stop();

                getter.SetOptimizedFunc();

                getter.Func.Target.Should().NotBeSameAs(getter);
                getter.Func.Method.Name.Should().Be(StaticFieldGetter.GetStaticValueOptimized);
                getter.Func.Method.DeclaringType.Should().NotBe(typeof(StaticFieldGetter <IBaz>));

                var  optimizedTimer = Stopwatch.StartNew();
                IBaz optimizedValue = getter.GetValue();
                optimizedTimer.Stop();

                optimizedValue.Should().Be(reflectionValue);
                optimizedTimer.Elapsed.Should().BeLessThan(reflectionTimer.Elapsed);
            }
        }
        public void StaticPropertyGetter1WorksWithBoxing()
        {
            var property = typeof(Garply).GetProperty(nameof(Garply.Baz));

            var getter = new StaticPropertyGetter <IBaz>(property);

            getter.Func.Target.Should().BeSameAs(getter);
            getter.Func.Method.Name.Should().Be(nameof(getter.GetValueReflection));
            getter.Func.Method.DeclaringType.Should().Be(typeof(StaticPropertyGetter <IBaz>));

            var  reflectionTimer = Stopwatch.StartNew();
            IBaz reflectionValue = getter.GetValue();

            reflectionTimer.Stop();

            getter.SetOptimizedFunc();

            getter.Func.Target.Should().NotBeSameAs(getter);
            getter.Func.Method.Name.Should().Be(StaticPropertyGetter.GetStaticValueOptimized);
            getter.Func.Method.DeclaringType.Should().NotBe(typeof(StaticPropertyGetter <IBaz>));

            var  optimizedTimer = Stopwatch.StartNew();
            IBaz optimizedValue = getter.GetValue();

            optimizedTimer.Stop();

            optimizedValue.Should().Be(reflectionValue);
            optimizedTimer.Elapsed.Should().BeLessThan(reflectionTimer.Elapsed);
        }
        public void FieldGetter2WorksWithBoxing()
        {
            var bar = new Bar {
                Baz = new Baz(123)
            };
            var field = typeof(Bar).GetField(nameof(Bar.Baz));

            var getter = new FieldGetter <Bar, IBaz>(field !);

            getter.Func.Target.Should().BeSameAs(getter);
            getter.Func.Method.Name.Should().Be(nameof(getter.GetValueReflection));
            getter.Func.Method.DeclaringType.Should().Be(typeof(FieldGetter <Bar, IBaz>));

            using (var gc = new GCNoRegion(4194304))
            {
                var  reflectionTimer = Stopwatch.StartNew();
                IBaz reflectionValue = getter.GetValue(bar);
                reflectionTimer.Stop();

                getter.SetOptimizedFunc();

                getter.Func.Target.Should().NotBeSameAs(getter);
                getter.Func.Method.Name.Should().Be(FieldGetter.GetValueOptimized);
                getter.Func.Method.DeclaringType.Should().NotBe(typeof(FieldGetter <Bar, IBaz>));

                var  optimizedTimer = Stopwatch.StartNew();
                IBaz optimizedValue = getter.GetValue(bar);
                optimizedTimer.Stop();

                optimizedValue.Should().Be(reflectionValue);
                optimizedTimer.Elapsed.Should().BeLessThan(reflectionTimer.Elapsed);
            }
        }
        public void PropertyGetter2WorksWithBoxing()
        {
            var bar = new Bar {
                Baz = new Baz(123)
            };
            var property = typeof(Bar).GetProperty(nameof(Bar.Baz));

            var getter = new PropertyGetter <Bar, IBaz>(property);

            getter.Func.Target.Should().BeSameAs(getter);
            getter.Func.Method.Name.Should().Be(nameof(getter.GetValueReflection));
            getter.Func.Method.DeclaringType.Should().Be(typeof(PropertyGetter <Bar, IBaz>));

            var  reflectionTimer = Stopwatch.StartNew();
            IBaz reflectionValue = getter.GetValue(bar);

            reflectionTimer.Stop();

            getter.SetOptimizedFunc();

            getter.Func.Target.Should().NotBeSameAs(getter);
            getter.Func.Method.Name.Should().Be(PropertyGetter.GetValueOptimized);
            getter.Func.Method.DeclaringType.Should().NotBe(typeof(PropertyGetter <Bar, IBaz>));

            var  optimizedTimer = Stopwatch.StartNew();
            IBaz optimizedValue = getter.GetValue(bar);

            optimizedTimer.Stop();

            optimizedValue.Should().Be(reflectionValue);
            optimizedTimer.Elapsed.Should().BeLessThan(reflectionTimer.Elapsed);
        }