I saw this sample code in SO that was saying one practice is bad and the other one is good. But I don’t understand why?
As a matter of fact I am getting that famous RCW COM object error and that post was saying this could be a reason.
public class SomeClass
{
private Interop.ComObjectWrapper comObject;
private event ComEventHandler comEventHandler;
public SomeClass()
{
comObject = new Interop.ComObjectWrapper();
// NO - BAD!
comObject.SomeEvent += new ComEventHandler(EventCallback);
// YES - GOOD!
comEventHandler = new ComEventHandler(EventCallback);
comObject.SomeEvent += comEventHandler
}
public void EventCallback()
{
// DO WORK
}
}
Edit: here is the link to the source: COM object that has been separated from its underlying RCW cannot be used
I think those two code snippets are the same and we don’t have any issues with strong/weak references here.
Background
First of all, if our
Interop.ComObjectWrapperprovides CLR event (i.e. event that stores event handlers in delegates) we’ll definitely got a strong reference fromComObjectWrapperto our object.Any delegate contains two parts:
Targetof typeobjectand Method Pointer to the particular method. IfTargetisnullthan callback points to the static method.Its impossible to have a delegate with
Targetof type WeakReference. There is so called Weak Event Pattern but it implements on top of EventManager instead of plain delegates.Storing event handler in the field will not help. Part 1
Internal event implementation means that after subscribing to the event:
comObjectobject implicitely holds an strong reference to theSomeClassobject. And this true regardless of what kind of subscribing technique your are using and whether ComObject is a COM object wrapper or not.Subscribing to the event adds implicit dependency between two objects in terms of lifetime. That’s why the most common memory leak in .NET world caused by subscribing to events of the long-lived objects. Event subscriber will not die till event holder accessible in the application.
Storing event handler in the field will not help. Part 2
But event if my assumption is not true and
ComObjectWrapperprovides some notion of Weak Event Pattern, saving event handler in the field will not help any way.Lets recap what event keyword mean:
Saving callback in current field (and basically we can treat private events as a simple delegate fields) will not change existing behavior.
We already know that delegate is a simple object that stores reference to the Target object (i.e.
SomeClassobject) and a method (i.e.public void EventCallBack()). This means that storing additional delegate in field adds additional reference to theSomeClassfrom theSomeClassitself.Basically, storing event handler in the field semantically equivalent to storing additional reference in SomeClass:
private SomeClass someClass;
public SomeClaas()
{
// This is basically the same as storing delegate
// in the comEventHandler field
someClass = this;
}
Storing strong reference in the
SomeClasswill not prolong lifetime of the current object. And this means that ifComObjectWrapperwill not hold a strong reference to theSomeClassobject storing event handler in thecomEventHandlerwill not prolong SomeClass’s lifetime and will not preventSomeClassfrom garbage collection.Conclusion
Storing event handler in the private field will not prolong object’s lifetime and will not prevent it from garbage collection anyway.
That’s why there is no difference between following code snippets in terms of object lifetime: