Unexpected C # compiler errors when trying to wrap COM interfaces to be IDisposable

(Note: I claim this is not a duplicate of Clearing Excel Interop Objects with IDisposable . This question asks "How do I do this?" My main question is "Why am I getting C # compiler errors?"

The main purpose here is to read (and later write) Excel files from a C # program. Google suggests that I add a link to Microsoft.Office.Interop.Excel and run from there. I've seen enough code to know that I am doing COM interop and therefore I want to get rid of the COM objects when I'm done with them. By adding a link (to version 14.0.0.0 from Microsoft.Office.Interop.Excel, in Visual Studio 2012), I'm off to the race.

Now I can't believe myself that I haven't forgotten to get all the calls Marshal.ReleaseComObject

in all the correct places, so I want to put my COM objects in expressions using

. Microsoft.Office.Interop.Excel.Application

not IDisposable

, and as far as I have discovered, Microsoft.Office.Interop.Excel

there is nothing else in space . But that's fine. I'm smart. I know how to fix this:

using Excel = Microsoft.Office.Interop.Excel;
//...
sealed class ExcelWrapper<T> : IDisposable
{
    public T Child { get; private set; }
    public ExcelWrapper(T child) { Child = child; }
    public static implicit operator ExcelWrapper<T>(T child) { return new ExcelWrapper<T>(child); }
    public static implicit operator T(ExcelWrapper<T> host) { return host.Child; }

    public void Dispose()
    {
        try { Marshal.ReleaseComObject(Child); }
        catch { }
    }
}
//...    
using (ExcelWrapper<Excel.Application> _xlApp = (ExcelWrapper<Excel.Application>)new Excel.Application()) // CS0030
{
    Excel.Application xlApp = _xlApp; // CS0029 and CS0266
}

      

Here are the error messages I don't understand (comments above point to lines with errors):

 error CS0030: Cannot convert type 'Microsoft.Office.Interop.Excel.Application' to 'ExcelWrapper<Microsoft.Office.Interop.Excel.Application>'
 error CS0029: Cannot implicitly convert type 'ExcelWrapper<Microsoft.Office.Interop.Excel.Application>' to 'Microsoft.Office.Interop.Excel.Application'

      

Why am I getting these error messages? Didn't I type public static implicit operator

? For some reason, I tried an autopsy ExcelWrapper

. The changes have changed, but I still don't understand what's going on:

error CS0266: Cannot implicitly convert type 'ExcelWrapper<Microsoft.Office.Interop.Excel.Application>' to 'Microsoft.Office.Interop.Excel.Application'. An explicit conversion exists (are you missing a cast?)

      

I'm still pretty sure there is an implicit conversion. But I can calm the compiler by using an explicit conversion if I am ok, leaving it ExcelWrapper

unsealed.

So what am I doing wrong here?

Why does the compiler completely ignore my conversion statements when the class is ExcelWrapper

sealed? And why does the compiler seem to ignore the notation implicit

(but not the rest of the statement) when the class is ExcelWrapper

not sealed?

+3


source to share


1 answer


Section 10.9.3 of the language specification states:

A conversion operator converts from the source type, indicated by the type of the conversion operator parameter, to the target type, indicated by the return type of the conversion operator. A class or structure is allowed to declare a conversion from a source type S to a target type T if everything is true:

- S and T are different types.
- Either S or T is the class or struct type in which the operator declaration takes place.
- Neither S nor T is object or an interface-type.
- T is not a base class of S, and S is not a base class of T.

      

Excel.Application

is an interface type, so you cannot create an implicit conversion.

The online version of the spec is a bit outdated and there is an updated version in your installation directory. New section for conversion rules 10.10.3

. For VS 2013, the specification is at:



C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC#\Specifications\1033

      

The updated version also contains instructions:

  • If T is an interface type, custom implicit conversions from S to T are ignored.

But it's not clear if this applies globally or only if there is an explicit conversion from S to T.

+3


source







All Articles