2012-01-19 8 views
18

C# 4, per semplificare l'interoperabilità COM, consente ai chiamanti di interfacce COM di omettere la parola chiave ref di fronte agli argomenti per i parametri ref.Errore nel compilatore C# o normale dispari COM?

Sono stato sorpreso di vedere oggi che questo si applica anche ai metodi di estensione che estendono le interfacce COM. Vedere il seguente, codice di compilazione:

using System; 
using System.Runtime.InteropServices; 

[ComImport, Guid ("cb4ac859-0589-483e-934d-b27845d5fe74")] 
interface IFoo { 
} 

static class Program { 

    public static void Bar (this IFoo self, ref Guid id) 
    { 
     id = Guid.NewGuid(); 
    } 

    static void Main() 
    { 
     Foo (null); 
    } 

    static void Foo (IFoo o) 
    { 
     Guid g = Guid.NewGuid(); 
     Console.WriteLine (g); 

     // note that g is passed as is, and not as ref g  
     o.Bar (g); 

     Console.WriteLine (g); 
    } 
} 

Non ho trovato nulla nelle specifiche per spiegare questo comportamento.

La mia sensazione sarebbe che il codice all'esterno dell'interfaccia COM, anche se si tratta di un metodo di estensione che estende un'interfaccia COM, dovrebbe seguire le normali regole C# e imporre l'uso della parola chiave ref. Ho quindi depositato uno bug on connect. Non che io pensi che questo sarà risolto, anche se è considerato come un bug, c'è già del codice là fuori basandosi su questo.

Bug? Non è un bug?

+3

Molto interessante. Le specifiche 4.0 sembrano essere ambigue qui.Dice che questo vale per i metodi di un tipo COM (sezione 22 + 22.1). Ma non sono riuscito a trovare nulla che dicesse esplicitamente o non dica che un metodo di estensione è considerato una parte di un tipo in questo modo. La mia ipotesi è che sia un bug. Sono sicuro che Eric sarà presto a chiarire. – JaredPar

+11

Questo sicuramente sembra un bug. Il mio autobus non funziona ancora oggi a causa del congelamento della pioggia sulla neve, quindi sono lontano dall'ufficio. Darei un'occhiata alla settimana prossima. Grazie per aver inserito il problema su Connect! –

risposta

2

Non penso che sia un bug; assomiglia più a "COM voodoo" come dici tu. Sotto il cofano, il compilatore C# emette qualcosa che è di fatto corretta, in questo modo:

private static void Foo(IFoo o) 
{ 
    ... 
    Guid g = Guid.NewGuid(); 
    Guid <>r__ComRefCallLocal0 = g; 
    Bar(o, ref <>r__ComRefCallLocal0); 
    ... 
} 

C# è in realtà piena di trucchi. Se si aggiunge un metodo per IFoo, in questo modo, per esempio,

[ComImport, Guid("cb4ac859-0589-483e-934d-b27845d5fe74")] 
interface IFoo 
{ 
    void Test([Optional] ref object test); 
} 

voi, ancora una volta, sarà in grado di dichiarare questo in C# 4:

static void Foo(IFoo o) 
{ 
    Guid g = Guid.NewGuid(); 
    o.Test(g); 
} 

Naturalmente, tutto questo funziona solo perché CSC .EXE ha una conoscenza approfondita dell'attributo ComImport. Questi nuovi trucchi Magic Interop sono stati aggiunti a C# 4.0 per essere in grado di interoperare facilmente con le interfacce COM esistenti. Bene, per le interfacce e i metodi di Microsoft Office soprattutto, e soprattutto gli eserciti di terribili parametri "ref missing" :-)

Non penso che questo sia completamente specificato da nessuna parte. Questo è tutto ciò che la specifica C# 4 ha da dire:

17.5 Attributi per l'interoperabilità Nota: questa sezione è applicabile solo all'implementazione di Microsoft .NET di C#. 17.5.1 Interoperazione con componenti COM e Win32 Il runtime .NET fornisce un gran numero di attributi che abilitano i programmi C# a interoperabili con componenti scritti utilizzando DLL COM e Win32. Per l'esempio , l'attributo DllImport può essere utilizzato su un metodo statico esterno per indicare che l'implementazione del metodo si trova in una DLL Win32 . Questi attributi si trovano nello spazio dei nomi System.Runtime.InteropServices e la documentazione dettagliata per questi attributi si trova nella documentazione di runtime .NET.

e qui ci sono alcune pagine su MSDN:

+2

Simon, so che ciò che il compilatore emette è valido. So anche che i siti di chiamata del metodo di interfaccia COM possono omettere il ref per argomenti di un parametro by ref, ma questa non è la domanda. La domanda è sapere se questo si applica ai metodi di estensione, in quanto non è specificato nelle specifiche. –

+0

Non è chiaro quello che sai e non sai dalla domanda. Ho provato a rispondere al "bug o non bug". Credo che non sia un * bug * perché è l'implementazione Microsoft .NET di C#, quindi l'implementazione e gli scenari supportati sono proprio ciò che Microsoft decide che deve essere. –

+0

@SimonMourier, ciò significherebbe che C# non potrebbe mai avere alcun bug, è una sciocchezza. Il compilatore C# è governato dalla specifica C#. Se il compilatore e le specifiche sono in conflitto, significa che c'è un bug. Potrebbe essere un bug nel compilatore o nelle specifiche e potrebbe anche essere deliberato, ma è sicuramente un bug. – svick

Problemi correlati