【问题标题】:Why is casting faster than reflection in .NET?为什么在 .NET 中投射比反射快?
【发布时间】:2009-07-02 17:09:00
【问题描述】:

我有一个事件处理程序,它需要确定类型并在匹配特定类型时执行代码。最初我们将它转​​换为一个对象,如果它不为空,我们执行代码,为了加快它的速度,我使用了反射,它实际上减慢了它的速度,我不明白为什么。

这是一个代码示例

Trace.Write("Starting using Reflection");
if (e.Item.GetType() == typeof(GridDataItem))
{
      bool isWatch = Convert.ToBoolean(e.Item.OwnerTableView.DataKeyValues[e.Item.ItemIndex]["IsWatch"]);
      if (isWatch)
      {
          e.Item.Style["Font-Weight"] = "bold";
      }
 }
 Trace.Write("Ending using Reflection");
 Trace.Write("Starting using Cast");
 GridDataItem gridItem = e.Item as GridDataItem;
 if (gridItem !=null)
 {
     bool isWatch = Convert.ToBoolean(gridItem.OwnerTableView.DataKeyValues[e.Item.ItemIndex]["IsWatch"]);
     if (isWatch)
     {
         gridItem.Style["Font-Weight"] = "bold";
     }
  }
  Trace.Write("Ending using Cast"); 

这是我得到的跟踪输出

Starting using Reflection  0.79137944962406 0.576538
Ending using Reflection    0.791600842105263    0.000221
Starting using Cast    0.791623353383459    0.000023
Ending using Cast      0.791649308270677    0.000026
Starting using Reflection  0.876253801503759    0.084604
Ending using Reflection    0.87631790075188 0.000064
Starting using Cast    0.87633445112782 0.000017
Ending using Cast      0.87634950075188 0.000015

这不是很多,但如果我们不得不随着时间的推移经常这样做,它可能会加起来。

【问题讨论】:

  • 一切都会随着时间的推移而累积。除非您有证据表明这实际上是随着时间的推移而增加的,否则不要为此感到压力。
  • 更多的是关于最佳实践,如果投射更快,那么我应该使用投射而不是反射
  • 完全不符合这个逻辑。如果投射是正确的,那么你应该使用投射而不是反射。正确性比速度更重要。
  • @Eric 在这种情况下,速度是决定因素,从普遍共识来看,使用强制转换是最佳实践,我的问题更多是关于在这种情况下强制转换更快,总是如此,什么是被认为是最佳实践

标签: c# .net reflection casting


【解决方案1】:

反射很慢,因为您正在查询程序集的元数据,而强制转换只会更改您引用的对象的类型。

程序集的元数据是一种有用的信息存储,但该信息最好在编译时而不是在执行时使用。编译器使用该元数据进行静态类型检查(除其他外)。您正在使用相同的元数据在执行时查找类型信息(如果您别无选择,这很好),这比强制转换慢得多。

【讨论】:

    【解决方案2】:

    反射必须在运行时进行并确定对象在运行时具有哪些属性等。转换告诉应用程序它应该期望一个对象具有 X 属性并且应该以某种方式运行。

    【讨论】:

      【解决方案3】:

      铸造告诉运行时您“知道”特定对象的类型。虽然您可能错了,但运行时会相信您,并且不会花费额外的时间来检查程序集的元数据。

      【讨论】:

        【解决方案4】:

        你为什么不使用is operator?我认为它更具可读性,因为您没有明确的演员表,然后检查。它只是检查变量的类型是否正确。

        if (e.Item is GridDataItem)
        {
            bool isWatch = Convert.ToBoolean(e.Item.OwnerTableView.DataKeyValues[e.Item.ItemIndex]["IsWatch"]);
            if (isWatch)
            {
                e.Item.Style["Font-Weight"] = "bold";
            }
        }
        

        【讨论】:

        • 实际上“is”确实在幕后做了演员。
        • 我的意思是它简化了代码(使其更具可读性),而不是它做任何根本不同的事情。我会澄清的。
        • 这实际上更慢开始 1.5268064962406 1.311905 结束 1.52701457443609 0.000208 开始 1.59114193383459 0.064127 结束 1.59120311278195 0.000pan
        • 难道不是“is”和“as”不使用转换运算符而强制转换吗?如果是这样,那么演员表并没有真正“在幕后”为“是”完成。
        • @Bob 这似乎很奇怪,因为根据 C# 参考,相当于:表达式是类型? (类型)表达式:(类型)空。见msdn.microsoft.com/en-us/library/cscsdfbt.aspx的备注。
        【解决方案5】:

        可以在运行时内进行整数比较,但反射涉及完整的方法调用。

        【讨论】:

          【解决方案6】:

          好吧,我想对最佳实践部分的简短回答是,如果您可以使用常规代码获得相同的结果,则永远不要使用反射。

          在优化代码时,通常最好估计花费在优化上的时间会在哪里获得最大的性能提升。用该语言原生地重新实现运算符很少会出现在该列表的顶部

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2020-02-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多