tags:

views:

198

answers:

7

I find a lot of cases where I think to myself that I could use relfection to solve a problem, but I usually don't because I hear a lot along the lines of "don't use reflection, it's too inefficient".

Now I'm in a position where I have a problem where I can't find any other solution than to use reflection with new T(), as outlined in this question & answer.

So I'm wondering if somebody can tell me reflection's specific intended usage, and if there's a set of guidelines to indicate when it's appropriate and when it isn't?

+2  A: 

Reflection is not inefficient. It is less efficient than direct calls. So personnaly I use reflection when there's no equivalent compile time safe method. IMHO the problem with reflection is not so much the efficiency but the fragility of the code as it uses magic strings which are very refactor unfriendly.

Darin Dimitrov
+8  A: 

If there's one thing that I hate hearing it's "don't use reflection, it's too inefficient".

Too inefficient for what? If you're writing a console application that's run once a month and isn't time critical, does it really matter if it takes 30 seconds instead of 28, because of you using reflection?

Guidelines for when it's inappropriate to use are ones that only you can really put together as they're heavily dependent on what you're doing and how efficient/performant alternatives are.

Rob
I like the point you're making rob, I keep hearing it but I'm sure the people I'm hearing it from heard it from someone else, who in turn heard it from someone else..... that's the point of the question. I'd like to know for myself when it's right or wrong
DaveDev
@DaveDev, it's never right or wrong in and of itself, it's how you use it. It's kinda like that saying "guns don't kill people, people do".
Rob
It's right when you need it, or when other solutions would be too complicated.
delnan
+2  A: 

I use it for plugin architecture - looking through assemblies in the plugin folder for methods marked with a custom attribute indicating info about the plugin - and in a logging framework. The framework detects a custom attribute on the assembly itself which holds information about the author of the assembly, the project, version information, and other tags that are logged along with everything in the stack trace.

Going to give away a 'trade secret', but it's a good one. The framework allows you to tag each method or class with a 'Story ref', e.g.

[StoryRef(Ref="ImportCSV1")]

...and the idea is it would integrate into our agile project management framework: if there were any exceptions thrown within that class/method, the logging method would use reflection to check for a StoryRef attribute in the stack trace, and if so that would be logged as an exception against that story. In the PM software you could see exceptions by Story (a story is like an extreme/agile use case).

I think that's a valid use, at least! Basically, when it just seems the most neat, and appropriate way to do it, I use reflection. Nothing else really comes into it - I can't think of an occasion you'd be using reflection to make that many calls that efficiency would come into it.

Kieren Johnstone
+8  A: 

It is often "fast enough", and if you need faster (for tight loops etc) you can do meta-programming with Expression or ILGenerator (perhaps via DynamicMethod), to make extremely fast code (including some tricks you can't do in C#).

Reflection is more commonly used for framework/library scenarios, where the library by definition knows nothing about the caller, and must work based on configuration, attributes or patterns.

Marc Gravell
On .NET 4.0, there's also the option of `dynamic`, which has optimizations such as call site caching. So there's an intermediate step between reflection and metaprogramming. In fact, I use `dynamic` whenever I can instead of directly using reflection, just for readability.
Stephen Cleary
+1 for ILGenerator and DynamicMethod; they can be a lot of fun and are perfect for the rare cases when Reflection is too slow (generally because you want to use it repeatedly in an inner loop.) They can be addictive, though and code using Emit is harder to maintain (some of my colleagues look at code I've written using Emit and treat it like some sort of voodoo magic.)
Dan Bryant
@Dan - you want to see some of the goo in protobuf-net "v2" then; meta-programming *in extremis* ;p
Marc Gravell
+6  A: 

A useful abstraction for code efficiency is to partition it in three categories of time, each about 3 orders of magnitude apart.

First is human-time. There's a lot you can do when you only need to keep a person happy with the performance of your code. Humans cannot perceive the difference between code that needs 10 milliseconds or 20 milliseconds, both look instant. And a human is forgiving when a program needs 6 seconds instead of 5, roughly 3 billion machine instructions more. Common examples of programs that run at human-time are compilers and point-and-click designers. Using reflection is almost never a problem.

Then there is I/O-time. When your program needs to hit the disk or the network. I/O is slow, restricted by mechanical motion in the case of the disk, bandwidth and latency in the case of a network. You can always tell when I/O is the bottleneck, your program is running but it isn't driving up the CPU load much. The operating system is constantly blocking the thread, making it wait until the I/O request is complete.

Reflection operates at I/O-time. To retrieve type data, the CLR must read the assembly metadata. And when that wasn't done before, your program will cause a page-fault, requiring the operating system to read the data from disk. What follows is that, roughly, reflection can make I/O bound code only twice as slow. Usually better because after the first perf hit, the metadata is cached and can be retrieved a lot quicker. Reflection is thus often an acceptable trade-off. The canonical example is serialization.

Then there's machine-time. The raw performance of a CPU core, when it isn't bogged down with reading data from RAM, is stupendous. A property getter can execute in somewhere between 0 and 1/2 a nanosecond. This does not compare favorably with, say, PropertyInfo.GetValue(). Both will keep the CPU busy, you'll see the CPU load for the core at 100%. But GetValue() costs hundreds if not thousands of machine code instructions. Not counting the time needed to page in the metadata. While not much an incremental time, it builds up fast when you loop.

If you cannot classify your reflection code in the human-time or I/O-time categories then reflection is unlikely to be an appropriate substitute for regular code.

Hans Passant
+1  A: 

The key to keeping reflection from slowing down your program is to not use it inside a loop. If you want to read a property from an object during startup (happens once), use reflection. You want to read a property from a list of 10,000 objects of unknown type, use reflection to get the property getter delegate once (search term: PropertyInfo.GetGetMethod), then call the delegate 10,000 types. There are plenty of examples of this on StackOverflow.

Ben Voigt
A: 

So I'm wondering if somebody can tell me reflection's specific intended usage, and if there's a set of guidelines to indicate when it's appropriate and when it isn't?

A bad example of reflection is this one from Wikipedia:

//Without reflection
Foo foo = new Foo();
foo.Hello();

//With reflection
Type t = Type.GetType("FooNamespace.Foo");
object foo = Activator.CreateInstance(t);
t.InvokeMember("Hello", BindingFlags.InvokeMethod, null, foo, null);

Here, there is no advantage to using reflection: The non-reflection-using code is not only more efficient, but easier to understand.

Good uses of reflection are things like serialization and object-relational mapping, which are easy to implement if you have a list of a class's properties, but otherwise require a custom-written function for each class.

dan04