在托管C ++ / CLI方式可选参数 [英] Optional parameters in managed C++/CLI methods

查看:218
本文介绍了在托管C ++ / CLI方式可选参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我如何申报C ++ / CLI有管理的方法,有一个可选的参数从C#中使用时?

我饰既是<一个参数href="http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.optionalattribute.aspx">Optional和<一href="http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.defaultparametervalueattribute.aspx">DefaultParameterValue属性(参见:<一href="http://blogs.msdn.com/b/samng/archive/2009/02/03/named-arguments-optional-arguments-and-default-values.aspx">How默认参数值都设有codeD ),但只有可选属性似乎兑现。


C ++ / CLI:

 公开引用类MyClass1的
{
 上市:
  MyClass1的([系统::运行:: InteropServices ::可选]
           [系统::运行:: InteropServices :: DefaultParameterValue(2)]
           INT myParam1)↑
  {
    系统::控制台:的WriteLine(myParam1);
  }
};
 

C#:

  VAR myInstance1 =新MyClass1的(); //编译并运行
 

输出的:

  0
 

预计输出:

  2
 

的Visual C#智能感知:

  MyClass1.MyClass1([INT myParam1 = 0]); //错误的默认值
                                  ↑
 


编辑:仔细一看有一个反汇编显示,C ++ / CLI编译器确实不能生成所需的 .PARAM [1] = INT32(2)指令。通过反射显示的IL code是错误的。

反射器:

 。方法公开hidebysig specialname rtspecialname实例无效.ctor([优化] INT32 myParam1)CIL管理
{
    .PARAM [1] = int32类型(2)//错误
    ...
 

ILDASM:

 。方法公开hidebysig specialname rtspecialname实例无效.ctor([优化] INT32 myParam1)CIL管理
{
    .PARAM [1]
    .custom实例无效[系统] System.Runtime.InteropServices.DefaultParameterValueAttribute ::。ctor的(对象)=(01 00 08 02 00 00 00 00 00)
    ...
 

解决方案

C#编译器不使用[DefaultParameterValue]属性设置为默认值,它使用.PARAM指令来获得嵌入在元数据中的价值。仅仅记录在CLI规范顺便说一句,只有分区第二,章15.4.1提到,它可以有一个FieldInit值,15.4.1.4是沉默了。

这就是责无旁贷,在C ++ / CLI编译器不知道如何生成的指令。你不能让这项工作。

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

解决方案

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.

这篇关于在托管C ++ / CLI方式可选参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆