如何在C ++ / CLI中声明一个在C#中使用时具有可选参数的托管方法?
我使用Optional和DefaultParameterValue属性修改了参数(请参阅:How default parameter values are encoded),但只有Optional属性才会被尊重。
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 )
...
答案 0 :(得分:28)
C#编译器不使用[DefaultParameterValue]属性来设置默认值,它使用.param指令来获取元数据中嵌入的值。只有在CLI规范btw中记录,只有Partition II,第15.4.1章提到它可以有一个FieldInit值,15.4.1.4对此保持沉默。
这就是降压停止的地方,C ++ / CLI编译器不知道如何生成指令。你无法做到这一点。
答案 1 :(得分:9)
有一个技巧可以使这个工作(解决方法)。 神奇的单词是可空的,对于可空类型,默认值总是" 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());
答案 2 :(得分:5)
作为一种解决方法,您可以重载构造函数,并使用委托。它将由JIT内联,并且应该以与默认参数值相同的最终结果结束。