在(据称)高性能代码中使用GetCurrentMethod

时间:2009-09-23 15:28:11

标签: .net vb.net performance reflection gettype

出于记录目的,我们的应用程序中的一些方法包括以下行:

Dim Log As ILog = GetLog(Reflection.MethodBase.GetCurrentMethod().DeclaringType)

我有可能被描述为对反思的非理性恐惧,我试图控制它。但是,在每秒执行一百次的方法中,这样的调用会引起我的注意。我不太了解反思;但是从简要介绍文档来看,我觉得我可以用以下内容替换以下内容:

Dim Log As ILog = GetLog(Me.GetType())

我的问题有三个:

  1. Me.GetType()实际上会返回与Type相同的GetCurrentMethod().DeclaringType吗?
  2. Me.GetType()是否实际上与GetCurrentMethod().DeclaringType做了不同的任何事情,或者它是否在幕后做同样的事情?
  3. 我根本不应该担心这件事吗?性能在此应用中至关重要;程序运行很好,但我们的业务性质是这样的,如果我们可以在这里和那里削减几微秒,这是有用的。

3 个答案:

答案 0 :(得分:14)

Me.GetType()是否返回GetCurrentMethod()。DeclaringType?

这取决于。 Me.GetType将始终返回对象的实际类型。 GetCurrentMethod()。DeclaringType将返回声明方法的类型。这些值在继承方案中可能不同。

考虑以下

Class C1
  Public Sub Foo() 
    ..
  End Sub
End Class
Class C2 
  Inherits C1
  ..
End Class

在Inside方法Foo中,如果你正在处理C1的实例,那么两个表达式将是相等的。但如果它是C2,它们将是不同的。

Me.GetType()与GetCurrentMethod()有什么不同.DeclaringType

是的,这些是非常不同的功能。 Me.GetType确定类的当前实例的运行时类型。 GetCurrentMethod.DeclaringType确定此方法声明的类型。

我根本不应该担心这个吗?

如果这是一个性能关键的情况,那么您确定要分析您不理解的API。特别是那些似乎涉及反思的人。但只有剖析器会告诉你哪个明确更快。我的钱在Me.GetType上。

答案 1 :(得分:8)

在您的情况下,this.GetType()将产生与MethodBase.GetCurrentMethod().DeclaringType相同的结果。有关两个调用将返回不同类型的情况,请参阅JaredPar的答案。

在一般情况下,公开成员的类型(通过MemberInfo.ReflectedType属性获得)和声明成员的类型(通过MemberInfo.DeclaringType属性获得)可能不同。

<强>更新

我只是使用C#进行了分析 - this.GetType()每次调用需要2.5 ns,而MethodBase.GetCurrentMethod().DeclaringType每次调用需要2490 ns - 所以你的速度大约为{{1} }}

[Intel Core 2 6400 2.13 GHz | 3.5 GiB | WinXP Pro SP2 | .NET FX 3.5 SP1 |发布|没有调试器]

答案 2 :(得分:0)

我刚才有同样的问题并找到了答案,但也许它不再是最新的,所以我发布我的测试结果......

我不知道dot net Framework的早期版本,但在dot net Framework 4中,我得到以下调用Times。所以表现不应该成为一个问题......

  • 首先调用MethodBase.GetCurrentMethod()。DeclaringType:0 ms - 221 ticks
  • 首先调用this.GetType():0 ms - 225 ticks

以下是产生此输出的代码:

        _txtReport.Text = string.Empty;
        var sw = new Stopwatch();

        sw.Start();
        var type = MethodBase.GetCurrentMethod().DeclaringType;
        sw.Stop();

        _txtReport.Text += string.Format("First Call to MethodBase.GetCurrentMethod().DeclaringType: {0} ms - {1} ticks{2}",
                                         sw.ElapsedMilliseconds, sw.ElapsedTicks, Environment.NewLine);

        sw.Start();
        var type1 = this.GetType();
        sw.Stop();

        _txtReport.Text += string.Format("First Call to this.GetType(): {0} ms - {1} ticks{2}",
                                         sw.ElapsedMilliseconds, sw.ElapsedTicks, Environment.NewLine);