1

Obviously reflection is a very extensive subject, but let's take a simple example: The "is" operator (A is B). What does it actually require the CLR to do? To look through the assembly's metadata, locate type A, walk up through its inheritance hierarchy and see if B is in there somewhere.

Now, isn't that all standard work for the CLR? I mean, the CLR does type-checking in runtime all the time in non-reflection code. Whenever you're calling methods or assigning values to parameters, the CLR must check in runtime whether the assigned object's type matches its designated parameter or variable.

So what makes reflection (and by that I mean the simple operators, such as "is" or "as"), relatively expensive?

  • 3
    There are compile time and runtime checks, reflection involves runtime checking. – Micha Wiedenmann May 12 '13 at 10:59
  • *"Whenever you're calling methods or assigning values to parameters, the CLR must check in runtime whether the assigned object's type matches its designated parameter or variable."* Those checks are done at *compile-time*. At runtime, the compiled code is mostly assumed to be correct in this regard (and you get different errors if that's not true). – T.J. Crowder May 12 '13 at 11:00
  • Separately: What makes you believe that `is` and `as` are expensive? – T.J. Crowder May 12 '13 at 11:01
  • You're obviously aware of that, but reflection (at least with a capital R) usually means something more than simple type checks. `is` isn't *that* expensive. In normal situations, it shouldn't make a big difference. But if you use `is` (and `as`) extensively, you probably have a more pressing problem to solve: polymorphism gone wrong. – stakx - no longer contributing May 12 '13 at 11:04
  • @OP Yes, your mistake is in thinking that type-checking is done at runtime. It isn't except for casting and explicit reflection. – Matthew Watson May 12 '13 at 11:06
  • As I said, the CLR does *runtime* checks all the time. Whenever you call a method with parameters, the CLR must make *runtime* checks to verify that the assigned objects match their parameters. So why is calling a method faster in any way than calling "is" or reflectively query the type's metadata in similar ways? – user2331443 May 12 '13 at 11:09
  • @user2331443: It is not simple type checks that are slow, but Reflection (as in `System.Reflection.*`, `Type`, `MemberInfo`, etc.), because constructing these rather heavy objects from assembly metadata is expensive. – stakx - no longer contributing May 12 '13 at 11:12

2 Answers2

3

The is operator is just as expensive as retrieving the Type of a class. The big difference is when that cost is incurred. In the case of the is operator, that happens when the JIT compiler retrieves the metadata from the assembly when it compiles the code. Which happens before you execute the code and is thus very likely to be a cost that you do not observe when you profile. Or dismiss as inevitable overhead, it is. Once that's done, using is in a loop is very cheap since the jitter has compiled a pointer value to the type's method table (aka the "type handle") directly into the machine code. No need to lookup the type again.

Not the case for Reflection, it doesn't run up front. You'll measure the cost of finding the assembly on disk and the page faults that page-in the metadata from the assembly file when you execute it. Which can be considerable, disks are slow. And afterwards the cost of finding the metadata cache slot back again.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • The *is* operator result can't be determined at compile-time due to polymorphism. Polymorphism can only be determined in runtime. – user2331443 May 13 '13 at 19:11
0

Covered by:

...and probably others.

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875