Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

How can I declare a managed method in C++/CLI that has an optional parameter when used from C#?

I've decorated the parameter with both an Optional and a DefaultParameterValue attribute (see: How default parameter values are encoded), but only the Optional attribute seems to be honored.


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

Output:

0

Expected Output:

2

Visual C# IntelliSense:

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

Edit: A closer look with a disassembler reveals that the C++/CLI compiler does indeed not generate the required .param [1] = int32(2) directive. The IL code shown by Reflector is wrong.

Reflector:

.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 ) 
    ...
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
355 views
Welcome To Ask or Share your Answers For Others

1 Answer

The C# compiler doesn't use the [DefaultParameterValue] attribute to set the default value, it uses the .param directive to get the value embedded in the metadata. Barely documented in the CLI spec btw, only Partition II, chapter 15.4.1 mentions that it can have a FieldInit value, 15.4.1.4 is silent about it.

That's where the buck stops, the C++/CLI compiler doesn't know how to generate the directive. You cannot make this work.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...