4

(Note: I claim this is not a duplicate of Clean up Excel Interop Objects with IDisposable. That question asks "How do I do it?" My primary question is "Why am I getting C# compiler errors?")

Primary goal here is to read (and later write) Excel files from a C# program. Google suggests that I should add a reference to Microsoft.Office.Interop.Excel and run from there. I saw enough code to know that I'm doing COM interop, and that I therefore want to dispose the COM objects when I'm done with them. With the reference added (to version 14.0.0.0 of Microsoft.Office.Interop.Excel, in Visual Studio 2012), I'm off to the races.

Now, I don't trust myself remember to get all the calls to Marshal.ReleaseComObject in all the right places, so I want to put my COM objects into using statements. Microsoft.Office.Interop.Excel.Application is not IDisposable, and, as far as I've discovered, neither is anything else in the Microsoft.Office.Interop.Excel namespace. 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
}

This presents me with error messages I don't understand (comments above indicate the 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? Did I not type public static implicit operator? For some reason, I tried unsealing ExcelWrapper.Things 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 an implicit conversion exists. But I can placate the compiler by using an explicit conversion, as long as I'm OK with leaving ExcelWrapper unsealed.

So, what am I doing wrong here?

Why does the compiler appear to completely ignore my conversion operators when the ExcelWrapper class is sealed? And why does the compiler appear to ignore the implicit designation (but not the rest of the operator) when the ExcelWrapper class is not sealed?

Community
  • 1
  • 1
DaleStan
  • 595
  • 2
  • 6
  • 19
  • @hans-passant: The answers to that question don't answer my question; I've edited my title and added a note explaining why I don't think this is a duplicate. Can you remove the duplicate flag, please? – DaleStan Dec 23 '14 at 00:35
  • No. Enough already, this nonsense needs to stop. – Hans Passant Dec 23 '14 at 00:38
  • @Hans: I still don't understand. I'm getting compiler errors that make no sense to me. But I happen to be using COM, so I'm not allowed to ask what those errors mean? – DaleStan Dec 23 '14 at 00:43
  • I don't see how the linked duplicate answers the OP's question. – Greg Dec 23 '14 at 00:51
  • `implicit operator`s can really wreck whatever is left of your strong typing in an Excel dynamic environment. This is a really deeply bad design. – H H Dec 23 '14 at 13:20

1 Answers1

3

Section 10.9.3 of the language specification states:

A conversion operator converts from a source type, indicated by the parameter type of the conversion operator, to a target type, indicated by the return type of the conversion operator. A class or struct is permitted to declare a conversion from a source type S to a target type T provided all of the following are 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, which is why you cannot create the implicit conversion.

The online version of the spec is a little outdated and there is an updated one in your install directory. The new section for the conversion rules is 10.10.3. For VS 2013 the spec is located at:

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

In the updated version, there is also a statement of:

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

But it is not entirely clear if that applies globally or only if an explicit conversion from S to T exists.

John Koerner
  • 37,428
  • 8
  • 84
  • 134
  • 1. I'd interpret this text as saying I can't create explicit conversions, though clearly the compiler is giving me the explicit conversion operators. (Until I try to run the code, that is; then everything blows up in my face again.) 2. Is it just me, or are those error messages the next best thing to useless? – DaleStan Dec 23 '14 at 01:57
  • @ThomasLevesque Found an answer to the why. Eric Lippert's [answer](http://stackoverflow.com/a/9231325/573218) gives a very good explanation. – John Koerner Dec 24 '14 at 13:39