The FAST Way To Create Instances With Reflection You're Not Using
March 15, 2024
• 732 views
When we're using reflection in C#, we have one really popular way to create instances of objects: Activator.CreateInstance. There's another contender though, and that's Type.InvokeMember. When it comes to reflection, we know that the performance is going to be slower than using ways that are available to us at compile time... but which of these two ways to create object instances is faster?
Better question: What's faster than BOTH of these ways and available to us in DotNet reflection?
View Transcript
using reflection in net we're able to create instances of objects dynamically we don't have to have a reference to the type at compile time which is pretty powerful but in reflection there's several different ways that we can create instances of objects so which one's best my name is Nick centino and I'm a principal software engineering manager at Microsoft in this video we're going to dive into some reflection we're going to look at different ways that we can create instances of objects we're going to compare the two leading ways that people use to do this and then we're going to see something else at the end that maybe works a little bit better we're going to be using benchmark.us quick reminder to check that pin comment for a link to my free weekly software engineering newsletter and my courses on dome train let's check out the
code okay so I thought it would be important to test out a couple of different variations for creating instances of objects we're going to look at three different classes here they're all pretty boring but it's all about the constructors so the first one that we're going to look at is this parameterless class very basic right there's nothing inside of it it's just going to be the default parameterless Constructor I feel like that's a pretty common scenario that people have classes they want to instantiate no dependencies to pass in so let's see how this one performs then I figured we should explore something that takes in a parameter I didn't know how many parameters to play around with but I figured at least one would be something different so this class here from line 136 to 144 just takes in one string parameter so we'll see
how that performs as well and finally because primary Constructors are getting tons of attention people either love them or hate them I'm mostly loving them but I wish there were some readon behavior and there's a couple of weird things I've come across but I figured toss these into the mix two that should be pretty important for us to look at and of course we'll come back to this top secret part in a little bit okay so as I mentioned we are going to be using ious how that works you could check out this video and then come right back here to continue on with this one if you want to learn more about benchmark.com list class is going to be setting up getting the type the reason I'm doing doing this is because I'm trying to just ensure that I'm taking out as much unnecessary
work from the different Benchmark methods is this going to take much time at all probably not I'm pretty sure at compile time we have this information that's why we can use type of but when you see the other one that's coming up you'll understand why I just tried to pull whatever was unnecessary to be in The Benchmark methods into this Global setup the first Benchmark we're going to look at is just calling the Constructor this is normally what we do without using any reflection pretty straightforward the next one one we're going to do is use activator create instance and I would say that this is probably the most popular approach for people to use and you'll notice that I've marked this one as the Baseline the reason I'm doing this is because when I was writing a Blog article about this I was comparing activator
create instance with this next one type invoke member so I wanted to get a baseline to activate or create instance is sort of the current champion that people are using most of the time and I didn't put it on the Constructor because we know this one's going to be faster I didn't want to have that and make it like all the other ratios compared to the Baseline of normal Constructor we're going to be crazy so this one was marked as Baseline primarily because I wanted to compare these two to begin with type invoke member is a little bit more verbose when we're calling it but this is the syntax to do it this is where you would pass in the name of the method but for a Constructor we don't need to do that we have binding flags for create instance which of course that's
what a Constructor does and because we're not passing in any parameters that last null is where we would put the argument that we want to provide overall pretty straightforward and the other Benchmark classes are almost identical it's just that we're going to be using the other class names here right so the other difference I'll call out is that when we're instantiating these we do have to pass in parameters so you'll see I just have hello world as the single string being passed in when you're calling these types of reflection methods you do need to pass the arguments in an array that's the only reason that there's an array created here this final class is basically the exact same thing it's just using the primary Constructor type so not going to spend much time doing that cuz I know you're curious about the benchmarks let's go
check those out okay starting with our parameterless Constructor if we look at the Constructor call as we might have imagined it's basically instant it's not even being picked up by The Benchmark run it's even telling us with a warning hey look this looks like it's too fast probably not going to be measured properly kind of figured that was going to happen but if we check out activator create instance and type invoke member we can see that activator create instance is over order of magnitude faster than type invoke members so definitely the clear winner here you can see what the ratio right for the compared to the Bas line clear winner activate or create instance when you don't have any Constructor parameters now once we start introducing parameters things get a little bit more interesting we can see that this Benchmark is the classic string parameter
class so one class it takes in one string as a Constructor parameter the Constructor is still the best way to go of course but if we're using reflection activate or create instance and and type invoke member are extremely similar we can see that type invoke member was only slightly slower the ratio here 1.03 just a little bit off arguably pretty negligible so if you had a really good reason to be using type invoke member over activator create instance performance- wise they're almost straight on par and when we look at the primary Constructor it's almost the same set of results right so of course the Constructor is going to be the fastest but activator create instance is only a tiny bit faster than type invoke member in fact when I ran these benchmarks to put my article together on my blog I noticed that both of
these were actually flipped in this particular case so they are very comparable so I would say again activator create instance is probably your best bet just because it's common people are used to it but if you had a really good reason to be using type invoke member performance-wise for these scenarios when you have parameters passed into your Constructor they're really not that different okay but I did say that I had something up my sleeve in terms of benchmarks here here and that's because there's something else we can explore to create instances of objects yes activator create instance is going to be the one that most people prefer and type invoke member not too far off in terms of performance but the syntax is a little bit for both there's something else we can use so let's jump back to visual studio and check this out
okay I'm going to add two more Benchmark methods to everything that we just saw and that's going to be because we're going to use Constructor info off of the type you'll notice here that I'm using Constructor info and inside the global setup that we had I'm instantiating this variable and it's basically done this way but I wanted to add these two variations because this is cheating a little bit I feel once we have the Constructor info calling invoke I feel like is probably very very close to calling a Constructor normally the reason that I think activator create instance and type invoke member take a little bit of extra time is because they're probably looking for this Constructor info or something very comparable right they're trying to find the method that they can call to create instances when we have the Constructor info we have the
method that can create the instances so I wanted to prove if we go do this explicitly and we go ask the type give me your Constructor that matches the syntax then we can call it and kind of put them back to back to get a a full picture the difference when we go to look at these other classes is just that we have to ask for the right Constructor so you'll notice that when I'm getting the Constructor info here I'm using type of string here in an array to say of all the parameters that we're looking for we just need one that has a single string parameter and then of course we pass in the string inside of an object array because that's what the syntax requires so I'm going to go rerun these benchmarks and we'll see how well these two do compared to
our others okay and the results are in are you ready if we check out The Benchmark results here I'm not going to go through the first three rows again because you already have seen those but if we check out the Constructor info inoke this is faster than activator Crea instance just by a little bit but it's certainly faster if you have to chain these two things together finding the Constructor info then invoking it it is slower than activator create instance so if you knew that you were going to be creating things over and over again and you could get that Constructor info one time then you might be able to save yourself a little bit of processing both of these times are extremely fast so I think activator create instance again if you're used to using it probably no issue but if you're trying to
squeeze every bit of drop performance out then maybe getting a snapshot of the Constructor info will save you a little bit of extra time but if we start looking at the situations where we need to pass in parameters how does this change we look at these results we can see the Constructor info if we already have access to it is much faster than activator create instance and type invoke member order of magnitude faster actually so Constructor is about 2 and a half NS and we can see that the Constructor info invokes is 15 so definitely slower than just using using the Constructor and I should have said this at the beginning but if you don't have to use reflection to create your objects don't just use the Constructor that might have been obvious but I felt obligated to kind of say it out loud if
we had to get the Constructor info then call it in line then we're still looking at something that is much faster than doing both activator create instance and type in voke members so these two options in my opinion are much better to use than what we're used to traditionally or at least when I say we are used to that I'm used to and I think what I see other people talking about online as well I would recommend if you have parameters start leveraging these but what about primary Constructors is this any different and no this is one of the situations where primary Constructors behave very similarly so that's good news but the performance characteristics of using Constructor info are very much the same primary Constructor and a traditional Constructor that takes in a parameter so in both of those cases I would still recommend use
Constructor info and those are the results for putting head-to-head different variations of creating instances of objects using reflection we saw that activator create instance is typically a pretty safe bet however if you start using parameters being passed into the constructors you want to call then I think Constructor info is going to save you a lot of extra time so trying to find ways that you can leverage that I think would be a great boost in performance of course if you have things like reflection on your hot path there's probably some other considerations that you might want to make but I might imagine that there are scenario where that exists I wanted to add in that all of this was being done because I didn't want to make assumptions about activator create instance and type inog member I saw some things online that were suggesting one
was always faster than the other and I said I think I need to prove this to myself because I hadn't seen any data points so I set off to go look into this and then I realized that Constructor info was of course another way that we could go do this and I got the hint from type invoke member because type invoke member can invoke any member and then I realized Iz that when we're using reflection we can go ask for Fields properties methods and I said well why don't I ask for the Constructor infos and sure enough it led to an interesting little realization here so if you thought that was cool and you want to see some more interesting Benchmark results you can check out this video next thanks and I'll see you next time
Frequently Asked Questions
What is the main advantage of using reflection to create instances of objects in .NET?
The main advantage of using reflection to create instances of objects in .NET is that it allows you to dynamically create instances without needing a reference to the type at compile time. This flexibility can be very powerful in scenarios where types are not known until runtime.
How does 'Activator.CreateInstance' compare to 'Type.InvokeMember' in terms of performance?
In my benchmarks, 'Activator.CreateInstance' is generally over an order of magnitude faster than 'Type.InvokeMember' when creating instances without parameters. When parameters are involved, both methods perform similarly, but 'Activator.CreateInstance' is still the more commonly used and slightly faster option.
When should I consider using 'ConstructorInfo.Invoke' instead of the traditional methods?
You should consider using 'ConstructorInfo.Invoke' if you're creating instances frequently and can cache the ConstructorInfo. In my tests, it proved to be faster than both 'Activator.CreateInstance' and 'Type.InvokeMember' when parameters are involved, making it a great choice for performance optimization.
These FAQs were generated by AI from the video transcript.