【发布时间】:2018-01-05 07:30:25
【问题描述】:
这个问题类似于this one,但假设我们在编译时知道成员名称。
假设我们有一个类
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" 一样快。
由于我几乎从未见过第二种方式,所以我有点困惑,现在我的问题是:
- 是不是走错了路?
- 第二种方式应该优于第一种方式还是相反?我不认为使用第二种方式有任何缺点。如果找不到该属性,(1) 和 (2) 都会抛出异常,不是吗?
- 为什么第二种方式看似更快,却很少使用?
【问题讨论】:
-
dynamic的主要目的是用于 LINQ 中的 匿名类型,或者作为一种更简单的方式与 COM 对话,而无需在超空间中处理所有乏味的事情,嗯,我的意思是类型图书馆之类的。所以,否则是的,你可能不会使用太多。另外,dynamic应该小心使用,因为即使它可以编译,如果找不到该成员(很像反射),您可能会收到运行时错误。当然除了匿名类型的情况 -
是的,你是对的,我也考虑过运行时错误,但我认为这两种情况(正如你已经说过的)都会导致运行时错误,所以我不认为这是在这种情况下似乎不鼓励使用
dynamic的唯一原因。 -
一般是的。 LINQ 中的匿名类型非常棒,就像匿名方法和 lambda 表达式一样
-
没有办法在你使用它之前检查“TheProperty”是否真的存在,但你可以通过反射。我猜这取决于你的用例。
-
帮自己一个忙,不要手动滚动微基准;要使您的基准以这种方式具有代表性,您必须考虑很多事情。利用别人的努力:benchmarkdotnet.org
标签: c# dynamic reflection