托管C++/CLI方法中的可选参数

dtb*_*dtb 28 .net c# c++-cli optional-parameters

在C#中使用时,如何在C++/CLI中声明具有可选参数的托管方法?

我使用OptionalDefaultParameterValue属性修饰了参数(请参阅:如何编码默认参数值),但只有Optional属性才被尊重.


C++/CLI:

public ref class MyClass1
{
 public:
  MyClass1([System::Runtime::InteropServices::Optional]
           [System::Runtime::InteropServices::DefaultParameterValue(2)]
           int myParam1)                                            ?
  {
    System::Console::WriteLine(myParam1);
  }
};
Run Code Online (Sandbox Code Playgroud)

C#:

var myInstance1 = new MyClass1();  // compiles and runs
Run Code Online (Sandbox Code Playgroud)

输出:

0
Run Code Online (Sandbox Code Playgroud)

预期产出:

2
Run Code Online (Sandbox Code Playgroud)

Visual C#IntelliSense:

MyClass1.MyClass1([int myParam1 = 0]);  // wrong default value
                                  ?
Run Code Online (Sandbox Code Playgroud)

编辑:仔细观察反汇编程序会发现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
    ...
Run Code Online (Sandbox Code Playgroud)

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 ) 
    ...
Run Code Online (Sandbox Code Playgroud)

Han*_*ant 28

C#编译器不使用[DefaultParameterValue]属性来设置默认值,它使用.param指令来获取元数据中嵌入的值.只有在CLI规范btw中记录,只有Partition II,第15.4.1章提到它可以有一个FieldInit值,15.4.1.4对此保持沉默.

这就是降压停止的地方,C++/CLI编译器不知道如何生成指令.你无法做到这一点.

  • 是的,bug,ildasm.exe向您展示真实的交易.仅存在属性.那里有一些混乱,因为VB.NET使用了该属性,它长期支持可选参数.您的代码将与VB.NET一起使用;) (3认同)

Mar*_*cel 9

有一个技巧可以使这个工作(解决方法).神奇的单词是可空的,对于可空类型,默认值始终为"null"(.HasValue == false)

例:

标头中的C++ CLI:

String^ test([Optional] Nullable<bool> boolTest);
Run Code Online (Sandbox Code Playgroud)

.cpp文件中的C++ CLI:

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

在C#中测试它:

MessageBox.Show(YourClass.test());
Run Code Online (Sandbox Code Playgroud)


Ben*_*igt 5

作为一种解决方法,您可以重载构造函数,并使用委托.它将由JIT内联,并且应该以与默认参数值相同的最终结果结束.