2

In C# and VB.Net I can use the CallerMemberNameAttribute to get the name of the invoker as a string:

public void Caller([CallerMemberName]string memberName = "")
{
   Debug.Print(memberName);
}

I would like to do the same in C++/CLI but somehow I cannot get it working. Tried several constructions and I am starting to wonder whether the C++/CLI compiler supports this attribute.

Here is a (simplified) implementation:

using namespace System::Runtime::CompilerServices;
public ref class InvokeExample
{
    Invoke([CallerMemberName][Optional]String^ name)
    {
        Debug::Print(name);
    }
}

When invoking this method in a C# application the value of name is null. Also tried with the attribute DefaultParameterValue but it didn't help either. Now running out of ideas.

Obvious answer would be, why not implementing in C#? Well, in this specific case I am limited to C++/CLI.

cklam
  • 156
  • 5

1 Answers1

1

I used reflector to view the differences between the C++/CLI and the C#/VB.Net version and they looked exactly the same.

Then used ILDASM and now I think I know why it doesn't work (after reading this post).

Here's the il code:

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

IL code from VB.Net differs from C# as follows:

.param [1] = nullref

I suspect that because the C++/CLI emits DefaultParameterValue instead of initializing .param[1] with a default value the C# compiler won't convert the value to the caller member name.

Would be handy if the MSDN pages describe such limitations for C++/CLI projects. Would save us a lot of time.

Community
  • 1
  • 1
cklam
  • 156
  • 5