6

For logging purposes, some methods in our application include the following line:

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

I have what might be described as an irrational fear of reflection, which I try to keep in check. However, calls like this in methods that are executed potentially a hundred times a second concern me. I don't know as much as I should about reflection; but from looking briefly over the documentation, it looks to me like I could replace the following with:

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

My question is three-fold:

  1. Does Me.GetType() actually return the same Type as GetCurrentMethod().DeclaringType?
  2. Does Me.GetType() actually do anything differently from GetCurrentMethod().DeclaringType, or is it doing the same thing under the hood?
  3. Should I not even be worried about this at all? Performance is critical in this application; the program runs fine, but the nature of our business is such that if we can shave off even a few microseconds here and there, that is useful.
Dan Tao
  • 125,917
  • 54
  • 300
  • 447

3 Answers3

14

Does Me.GetType() return the as GetCurrentMethod().DeclaringType?

It depends. Me.GetType will always return the actual type of an object. GetCurrentMethod().DeclaringType will return the type in which the method was declared. These values can be different in inheritance scenarios.

Consider the following

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

Inside method Foo the two expressions would be equal if you were dealing with an instance of C1. But if it was C2 they would be different.

Does Me.GetType() do anything differently from GetCurrentMethod().DeclaringType

Yes these are very different functions. Me.GetType determines the runtime type of the current instance of the class. GetCurrentMethod.DeclaringType determines in what type was this method declared.

Should I not even be worried about this at all?

If this is a performance critical scenario then yes you make sure you profile APIs you do not understand. Especially those that appear to involve reflection. But only a profiler will tell you which is definitively faster. My money is on Me.GetType though.

JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • 1
    Thanks a lot for the full explanation. As I mentioned in a separate comment on a different answer, in *this* scenario the difference between these two functions (as I understand them) is not particularly important. Also: from profiling, it certainly looks like you put your money in the right place. – Dan Tao Sep 23 '09 at 16:14
8

In your situation this.GetType() will yield the same result as MethodBase.GetCurrentMethod().DeclaringType does. See JaredPar's answer for a situation where both calls will return different types.

In the general case the type exposing a member (obtained via the MemberInfo.ReflectedType property) and the type declaring a member (obtained via the MemberInfo.DeclaringType property) may differ.

UPDATE

I just profiled it using C# - this.GetType() required 2.5 ns per call while MethodBase.GetCurrentMethod().DeclaringType required 2490 ns per call - so you have a speed up of about factor 1200.

[Intel Core 2 6400 2.13 GHz | 3.5 GiB | WinXP Pro SP2 | .NET FX 3.5 SP1 | Release | Without Debugger]

Daniel Brückner
  • 59,031
  • 16
  • 99
  • 143
  • In that case, do you happen to know whether `Me.GetType()` is actually any faster than `MethodBase.GetCurrentMethod().DeclaringType`? – Dan Tao Sep 23 '09 at 15:38
  • 1
    Nicely done. Thanks for the profiling, which I actually just did myself as well (had a spare moment) and saw the same results as you. – Dan Tao Sep 23 '09 at 16:00
  • @Daniel, they do not return the same result in all scenarios. See my answer. – JaredPar Sep 23 '09 at 16:04
  • @JaredPar You are right. While I am aware of the difference, I missed this scenario exposing the difference in the given use case. – Daniel Brückner Sep 23 '09 at 16:08
  • After modifying the my code to (almost) remove the profiling overhead, the speed-up increased from about 300 to more then 1200. – Daniel Brückner Sep 23 '09 at 16:10
  • @MarkJ: Fair enough, but here's the thing: `GetLog` (from a 3rd party vendor) really just returns a log from a collection whose keys are strings, where each string represents a given type. The methods in question are declared within a class that is not inherited. Even given the difference between `GetCurrentMethod().DeclaringType` and `GetType`, in this scenario they aren't particularly important (the log will be sufficiently informative in either case). Considering the performance difference we found, I think this was worth investigating. – Dan Tao Sep 23 '09 at 16:10
0

I just had the same question and found this answer, but maybe it is not up to date any more so I post my testresults...

I don't know about previous versions of the dot net Framework, but in dot net Framework 4 I get the following calling Times. So performance should not be an issue any more...

  • First Call to MethodBase.GetCurrentMethod().DeclaringType: 0 ms - 221 ticks
  • First Call to this.GetType(): 0 ms - 225 ticks

Here is the code which produced this output:

        _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);
Markus
  • 2,184
  • 2
  • 22
  • 32
  • 10
    You did not reset the stopwatch. This means `GetCurrentMethod()` actually took 221 ticks, whereas `GetType()` took *4* ticks (225 - 221). By itself an insignificant amount of time in either case, but `GetType()` is still clearly much faster. – Dan Tao Sep 13 '11 at 06:55
  • According to my measurings the reflection way also took 22x ticks, whereas the other one took 2 ticks. So in performance-critical solutions the latter is the wanted way. But in all other scenarios i would prefer the first one - since 1ms = 10 000 ticks - the action takes 0.0225ms - and the reflection would come in action only when tracing needed. – Vladimír Hála Jul 21 '20 at 09:36