parametro parameter opcional method make define c# .net c++-cli optional-parameters

c# - parameter - Parámetros opcionales en métodos C++/CLI administrados



optional parameter in c# (3)

¿Cómo puedo declarar un método administrado en C ++ / CLI que tiene un parámetro opcional cuando se usa desde C #?

He decorado el parámetro con un atributo Optional y un DefaultParameterValue Parámetro predeterminado (ver: Cómo se codifican los valores de los parámetros predeterminados ), pero parece que solo se cumple el atributo Opcional

C ++ / CLI:

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

DO#:

var myInstance1 = new MyClass1(); // compiles and runs

Salida :

0

Rendimiento esperado:

2

Visual C # IntelliSense:

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

Edición: Una mirada más cercana con un desensamblador revela que el compilador C ++ / CLI no genera la .param [1] = int32(2) . El código IL mostrado por Reflector es incorrecto.

Reflector:

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

ILDASMA:

.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 ) ...


Como solución alternativa, puede sobrecargar el constructor y usar la delegación. El JIT lo integrará y debe terminar con el mismo resultado final como valor de parámetro predeterminado.


El compilador de C # no usa el atributo [DefaultParameterValue] para establecer el valor predeterminado, usa la directiva .param para obtener el valor incrustado en los metadatos. Apenas documentado en la especificación de CLI por cierto, solo en la partición II, el capítulo 15.4.1 menciona que puede tener un valor FieldInit, 15.4.1.4 no dice nada.

Ahí es donde el dinero se detiene, el compilador de C ++ / CLI no sabe cómo generar la directiva. No puedes hacer que esto funcione.


Hay un truco para hacer que esto funcione (solución). la palabra mágica es anulable, ya que para los tipos anulables el valor predeterminado es siempre "nulo" (.HasValue == falso)

Ejemplo:

C ++ CLI en el encabezado:

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

C ++ CLI en el archivo .cpp:

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

Para probarlo en C #:

MessageBox.Show(YourClass.test());