18

C# 4 では、COM 相互運用を簡素化するために、COM インターフェイスの呼び出し元が by ref パラメーターの引数の前にある ref キーワードを省略できるようになっています。

今日、これが COM インターフェイスを拡張する拡張メソッドにも当てはまることを知って驚きました。次のコンパイル、コードを参照してください。

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);
    }
}

この動作を説明する仕様は見つかりませんでした。

COM インターフェイスを拡張する拡張メソッドであっても、COM インターフェイスの外側のコードは、通常の C# ルールに従い、ref キーワードの使用を強制する必要があると思います。したがって、私はconnect にバグを報告しました。これが修正されるとは思いません。バグと見なされても、これに依存するコードが既に存在します。

バグ?バグじゃない?

4

1 に答える 1

2

バグではないと思います。あなたが言うように、それは「COMブードゥー」のように見えます。内部的には、C# コンパイラは次のように、実際には正しいものを出力します。

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

実際、C# にはたくさんのトリックがあります。たとえば、次のように IFoo にメソッドを追加すると、

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

繰り返しますが、C# 4 でこれを宣言できます。

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

もちろん、これはすべて、CSC.EXE が ComImport 属性をよく知っているためにのみ機能します。これらの新しい魔法の相互運用機能が C# 4.0 に追加され、既存の COM インターフェイスと簡単に相互運用できるようになりました。まあ、主にMicrosoft Officeのインターフェースとメソッド、そして特に恐ろしい「参照欠落」パラメータの軍隊のために:-)

これはどこにも完全に指定されているとは思いません。これは、C# 4 仕様が述べなければならないことのすべてです。

17.5 相互運用のための属性 注: このセクションは、C# の Microsoft .NET 実装にのみ適用されます。17.5.1 COM および Win32 コンポーネントとの相互運用 .NET ランタイムは、C# プログラムが COM および Win32 DLL を使用して記述されたコンポーネントと相互運用できるようにする多数の属性を提供します。たとえば、静的 extern メソッドで DllImport 属性を使用して、メソッドの実装が Win32 DLL にあることを示すことができます。これらの属性は System.Runtime.InteropServices 名前空間にあり、これらの属性の詳細なドキュメントは .NET ランタイム ドキュメントにあります。

MSDN のいくつかのページを次に示します。

于 2012-01-19T18:17:19.750 に答える