0

To make sure that a COM object that I need to create is freed/released as soon I didn't need it anymore is simple with the using statement.

using (dynamic a = new MyFooCOMApplication()) 
{ 
...
}

Now suppose I have a Foo COM object. This Foo object has a COM enumeration called Fields, and Fields itself return item of type Field. Assume that the Field object has a property Value, I can write code like:

a.Fields("Test").Value

Or in other words:

a.Fields.Item("Test").Value = 0;

With this statement two temporary objects are created. One of type Fields, one of type Field.

Now my question: Does C# implicit uses a using clause for the both temporary objects or must I write:

using (dynamic fields=a.Fields) 
{
   using (dynamic field=fields.Item("Test")) 
   {
     field.Value = 0;
   }
}

Just to clarify:

  1. I use an external COM server. So freeing the objects is absolutely required.
  2. Calling the GC.Collect isn't "what I feel" a good style. Even if hundreds of programmers are using it.
  3. The code itself is again inside an VSTO Addin of Outlook. So I want to work as clean as possible.
xMRi
  • 14,982
  • 3
  • 26
  • 59
  • `Does C# implicit uses a using clause for the both temporary objects` No it does not. – mjwills Jun 02 '20 at 07:17
  • 1
    Your use of `using` is quite odd there. I'd be surprised to see a RCW implement `IDisposable`. Does your COM object implement `IDisposable`? – mjwills Jun 02 '20 at 07:18
  • When it comes to COM; in general: don't assume anything to be released out of the box ;-) – Stefan Jun 02 '20 at 07:18
  • To be sure, you can play around with Marshal.ReleaseComObject; it shows you the reference count.https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshal.releasecomobject?view=netcore-3.1 – Stefan Jun 02 '20 at 07:19
  • In COM world (using .NET) there are two basic schools of thought. a) Manually release everything (this is my school of thought) with https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshal.releasecomobject?view=netcore-3.1 b) Call `GC.Collect` frequently and hope for the best. I live in camp a), but most people live in camp b). a) is more reliable - but more fiddly and easier to miss something. b) is less reliable (theoretically at least) - but easier to get "largely" right. – mjwills Jun 02 '20 at 07:20
  • It also depends on the type of objects below. For some type of objects (aka: the one that just allocate ram for example) it's not strictly necessary to dispose, you can wait for GC collect (just like in standard .NET). For some others (that hold a crucial or context-based or thread-based resource), you have to do it yourself and ReleaseComObject. Add to that the fact that some COM objects are in fact in some cross-referencing tree of objects, and released automatically (w/o you having to do anything)... There's no magic bullet. The full 'using' way works but it can be tedious. – Simon Mourier Jun 02 '20 at 07:28
  • `The full 'using' way works but it can be tedious.` Is that true though @SimonMourier? Do RCWs implement `IDisposable` by default? – mjwills Jun 02 '20 at 07:44
  • `Just to clarify:` Based on that, have a read of https://ausdotnet.wordpress.com/category/technical/com-interop/ . Short answer - if you are in camp a) (which you seem to be) then you need to be very thorough. – mjwills Jun 02 '20 at 07:45
  • @mjwills - no, you'll have to use a wrapper like in DaggeJ answer. I've sometimes used a similar approach: https://github.com/smourier/DirectN/blob/master/DirectN/DirectN/ComObject.cs – Simon Mourier Jun 02 '20 at 07:49

0 Answers0