[英]Why not use `dynamic` instead of reflection when the property is known?
这个问题与此类似,但是假设我们在编译时知道成员名称。
假设我们有一堂课
public class MyClass
{
public string TheProperty { get; set; }
}
在另一种方法中,我们想设置该类实例的TheProperty
成员,但是在编译时我们不知道实例的类型,而在编译时我们只知道属性名称。 因此,正如我所看到的,现在有两种方法可以做到这一点:
object o = new MyClass(); // For simplicity.
o.GetType().GetProperty("TheProperty").SetValue(o, "bar"); // (1)
((dynamic) o).TheProperty = "bar"; // (2)
我使用System.Diagnostics.Stopwatch
类测量了该测试用例,以发现反射花费了475个滴答声 ,而使用dynamic
花费了0个滴答声 ,因此与直接调用new MyClass().TheProperty = "bar"
一样快new MyClass().TheProperty = "bar"
。
由于我几乎从未见过第二种方法,因此我有些困惑,现在我的问题是:
(...)反射花费475个滴答声,而使用动态的方式花费0个滴答声(...)
那是完全错误的。 问题在于您不了解dynamic
工作原理。 我将假设您正确设置了基准:
这是您可能没有做的关键部分:
为什么3很重要? 因为运行时将缓存动态调用并重用它! 因此,在幼稚的基准测试实现中,如果您做得正确,则会招致初始动态调用(使该方法无效)的开销,因此您将无法进行度量。
运行以下基准:
public static void Main(string[] args)
{
var repetitions = 1;
var isWarmup = true;
var foo = new Foo();
//warmup
SetPropertyWithDynamic(foo, isWarmup); //JIT method without caching the dynamic call
SetPropertyWithReflection(foo); //JIT method
var s = ((dynamic)"Hello").Substring(0, 2); //Start up the runtime compiler
for (var test = 0; test < 10; test++)
{
Console.WriteLine($"Test #{test}");
var watch = Stopwatch.StartNew();
for (var i = 0; i < repetitions; i++)
{
SetPropertyWithDynamic(foo);
}
watch.Stop();
Console.WriteLine($"Dynamic benchmark: {watch.ElapsedTicks}");
watch = Stopwatch.StartNew();
for (var i = 0; i < repetitions; i++)
{
SetPropertyWithReflection(foo);
}
watch.Stop();
Console.WriteLine($"Reflection benchmark: {watch.ElapsedTicks}");
}
Console.WriteLine(foo);
Console.ReadLine();
}
static void SetPropertyWithDynamic(object o, bool isWarmup = false)
{
if (isWarmup)
return;
((dynamic)o).TheProperty = 1;
}
static void SetPropertyWithReflection(object o)
{
o.GetType().GetProperty("TheProperty").SetValue(o, 1);
}
public class Foo
{
public int TheProperty { get; set; }
public override string ToString() => $"Foo: {TheProperty}";
}
找出第一次运行与后续运行之间的区别?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.