在C#和VB.Net中,我可以使用 CallerMemberNameAttribute 将调用者的名称作为字符串获取:
public void Caller([CallerMemberName]string memberName = "")
{
Debug.Print(memberName);
}
我想在C ++ / CLI中做同样的事情,但不知怎的,我无法让它工作。尝试了几种结构,我开始怀疑C ++ / CLI编译器是否支持这个属性。
这是一个(简化的)实现:
using namespace System::Runtime::CompilerServices;
public ref class InvokeExample
{
Invoke([CallerMemberName][Optional]String^ name)
{
Debug::Print(name);
}
}
在C#应用程序中调用此方法时,name的值为null。还尝试使用属性 DefaultParameterValue ,但它也没有帮助。现在已经没有了想法。
明显的答案是,为什么不在C#中实现? 好吧,在这种特殊情况下,我仅限于C ++ / CLI。
答案 0 :(得分:1)
我使用了反射器来查看C ++ / CLI和C#/ VB.Net版本之间的差异,它们看起来完全一样。
然后使用ILDASM,现在我想我知道为什么它不起作用(在阅读post之后)。
这是il代码:
C ++ / CLI
.method public hidebysig instance string
Caller([opt] string methodName) cil managed
{
.param [1]
.custom instance void [System]System.Runtime.InteropServices.DefaultParameterValueAttribute::.ctor(object) = ( 01 00 0E 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.CallerMemberNameAttribute::.ctor() = ( 01 00 00 00 )
// Code size 2 (0x2)
.maxstack 1
IL_0000: ldarg.1
IL_0001: ret
} // end of method ClassCPP::Caller
C#
.method public hidebysig instance string
Caller([opt] string methodName) cil managed
{
.param [1] = ""
.custom instance void [mscorlib]System.Runtime.CompilerServices.CallerMemberNameAttribute::.ctor() = ( 01 00 00 00 )
// Code size 2 (0x2)
.maxstack 1
.locals init ([0] string CS$1$0000)
IL_0000: ldarg.1
IL_0001: ret
} // end of method ClassCS::Caller
VB.Net的IL代码与C#的不同之处如下:
.param [1] = nullref
我怀疑因为C ++ / CLI发出DefaultParameterValue而不是使用默认值初始化.param [1],所以C#编译器不会将该值转换为调用者成员名称。
如果MSDN页面描述了C ++ / CLI项目的这些限制,那将会很方便。会为我们节省很多时间。