Question

In my code I'm instantiating a legacy Delphi object through a COM interface. This class needs to be instantiated many times, so in order to lower the overhead of instantiating it I cache it at a point where 70% of all the calls have the common resulting object.

However, when I alter the object after it is cached, the changes are persisted in the cache too. This makes me think the COM wrapper instance is passed by ref instead of by value.
How can I make sure that the object in cache is passed by value rather then by ref?

Was it helpful?

Solution

I think that, if it's possible to do at all, you need to explicitly clone a copy of the object and then cache the copy. See for example the MemberwiseClone method, and others mentioned in answers to Cloning objects in C#.

OTHER TIPS

First, is this needed?

I'm not an advocate of "measuring solve all performance problems", but in your case, you should.

The overhead of instantiating a COM object (after the first call penalty) as such is very low - remember it was designed to afford many small objects on computers of 15 years ago. I assume the .NET overhead isn't much more - so the question is the objects own initialization.

You can check that easily by instantiating 1000 objects in a tight loop (throw away the first call, it can be very expensive and would spoil the average)

COM objects are inherently by reference
There is no "pass by value" for COM objects, as their basic interface is a reference counted pointer to the instance, and COM doesn't expose a generic "Clone" method.

possible solution: Copy-on-Write
If an only if instantiation is really expensive, and the majority of calls can be done through a default instance, you can implement a copy-on-write scheme.

You need to create a wrapper class that holds a reference to the default instance, and a reference to a private instance initialized to 0.

As long as the private instance is null, all getter functions forward to the default instance, otherwis, they forward to the private instance.

Every setter/mutator call forwards to the private instance, creating it when it doesn't exist.

This would delay creation for the private instance to the first mutating call. However, you have to wrap the entire all interfaces of interest for this component.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top