web-dev-qa-db-ja.com

マネージC ++ / CLIメソッドのオプションのパラメーター

C#から使用するときにオプションのパラメーターを持つC++/CLIでマネージドメソッドを宣言するにはどうすればよいですか?

オプション 属性と DefaultParameterValue 属性の両方でパラメーターを装飾しました(参照: デフォルトのパラメーター値のエンコード方法 )が、オプションのみ属性は尊重されているようです。


C++/CLI:

_public ref class MyClass1
{
 public:
  MyClass1([System::Runtime::InteropServices::Optional]
           [System::Runtime::InteropServices::DefaultParameterValue(2)]
           int myParam1)                                            ↑
  {
    System::Console::WriteLine(myParam1);
  }
};
_

C#:

_var myInstance1 = new MyClass1();  // compiles and runs
_

出力

_0
_

期待される出力:

_2
_

Visual C#IntelliSense:

_MyClass1.MyClass1([int myParam1 = 0]);  // wrong default value
                                  ↑
_

編集:逆アセンブラを詳しく見ると、C++/CLIコンパイラが実際に必要な.param [1] = int32(2)ディレクティブを生成していないことがわかります。 Reflectorによって表示されるILコードが間違っています。

リフレクター:

_.method public hidebysig specialname rtspecialname instance void .ctor([opt] int32 myParam1) cil managed
{
    .param [1] = int32(2)  // bug
    ...
_

ILDASM:

_.method public hidebysig specialname rtspecialname instance void .ctor([opt] int32 myParam1) cil managed
{
    .param [1]
    .custom instance void [System]System.Runtime.InteropServices.DefaultParameterValueAttribute::.ctor(object) = ( 01 00 08 02 00 00 00 00 00 ) 
    ...
_
29
dtb

C#コンパイラは、[DefaultParameterValue]属性を使用してデフォルト値を設定するのではなく、.paramディレクティブを使用してメタデータに埋め込まれた値を取得します。 CLI仕様にほとんど記載されていませんが、パーティションIIの15.4.1章でのみ、FieldInit値を持つことができると記載されており、15.4.1.4はそれについて沈黙しています。

ここで問題が発生し、C++/CLIコンパイラはディレクティブの生成方法を知りません。これを機能させることはできません。

28
Hans Passant

これを機能させるための秘訣があります(回避策)。魔法の言葉はnull許容型であり、null許容型の場合、デフォルトは常に「null」です(.HasValue == false)

例:

ヘッダーのC++ CLI:

String^ test([Optional] Nullable<bool> boolTest);

.cppファイルのC++ CLI:

String^ YourClass::test(Nullable<bool> boolTest)
{
    if (!boolTest.HasValue) { boolTest = true; }
    return (boolTest ? gcnew String("True") : gcnew String("False"));
}

c#でテストするには:

MessageBox.Show(YourClass.test());
9
Marcel

回避策として、コンストラクターをオーバーロードし、委任を使用することができます。これはJITによってインライン化され、デフォルトのパラメーター値と同じ最終結果になるはずです。

5
Ben Voigt