【问题标题】:Property / Method inlining and impact on Reflection属性/方法内联和对反射的影响
【发布时间】:2011-07-14 10:34:07
【问题描述】:

Valentin Kuzub 对我的answer 对 SO 的一个问题发表了评论,他认为 JIT 编译器内联属性将导致反射停止工作。

案例如下:

class Foo
{
    public string Bar { get; set; }

    public void Fuzz<T>(Expression<Func<T>> lambda)
    {
    }
}

Fuzz(x => x.Bar);

Fuzz 函数接受 lambda 表达式并使用反射来查找属性。这是 MVC 在 HtmlHelper 扩展中的常见做法。

我认为即使Bar 属性被内联,反射也不会停止工作,因为它是对Bar 的调用,它将被内联,typeof(Foo).GetProperty("Bar") 仍将返回一个有效的PropertyInfo

您能否确认一下,或者我对方法内联的理解是错误的?

【问题讨论】:

标签: c# reflection inlining


【解决方案1】:

JIT 编译器在运行时运行,它不能重写存储在程序集中的元数据信息。反射读取程序集以访问此元数据。所以 JIT 编译器对反射没有影响。

编辑: 实际上,有几个地方 C# 编译器本身在编译期间“内联”了一些信息。例如,常量、枚举和默认参数是“内联的”,因此您无法在反射期间访问它们。但这绝对与您的具体情况无关。

【讨论】:

  • 默认属性是什么意思?
  • 您可以将enums 添加到您的列表中。
【解决方案2】:

是的,当我想得更多时,我猜只有内联属性可能会失败的方法 INotifyPropertyChanged 接口正确的工作是如果您使用的是基于反射的方法,例如

public Count
{
get {return m_Count;}
 set { m_Count=value;
      GetCurrentPropertyNameUsingReflectionAndNotifyItChanged();}
}

如果像您这样使用,则表明程序集中确实存在元数据,并且将从那里成功获取属性名称。

让我们俩都在思考。

【讨论】:

  • 究竟如何?方法将不是从属性调用,而是从使用属性的方法调用,结果名称不会是 Count,而是不同的东西(很可能是方法名称,而不是属性名称)
  • 你的方法GetCurrentPropertyNameUsingReflectionAndNotifyItChanged是在分析调用栈吗?
  • 是的。如您所见,没有任何东西传递给它。这是一种基于通用反射的方法,如果永远不会发生内联,那就太好了。在视图模型库中实现一种方法,从所有属性中调用它并享受..
  • 然后你必须用MethodImplAttribute标记你的属性来停止内联。
【解决方案3】:

我个人同意@Sergey:

考虑到内联发生在 JIT 编译器端,但之前生成的元数据,它不应该以任何方式影响反射。顺便问下,好问题,点赞+1

【讨论】:

    【解决方案4】:

    表达式树无论如何都不能内联,因为它们是表达式(抽象语法树)的表示,而不是表达式本身。

    委托,即使它们可以内联,仍将在其属性中携带有关被调用的方法和目标的数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-17
      • 1970-01-01
      • 2013-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-19
      • 1970-01-01
      相关资源
      最近更新 更多