Cross-language Extension Method Calling

Extension methods are a concise way of binding functions to particular types.

In my last post, I showed how Extension methods can be created in the .NET 2.0 environment.
In this post, I discuss calling the extensions from other languages.

Most of the differences I find between the Dot Net languages are mainly syntax.  The declaration of Extensions is no exception.  There is, however, a distinct difference with the framework accepting excensions made with C++ that differs from C# and VB. 

When calling the C++ extension from C#, the compiler will SOMETIMES say there is no definition for DoCPP with the error:
'string' does not contain a definition for 'DoCPP' and no extension method 'DoCPP' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)

If I recompile, the error goes away.

The strangest problem with calling the C++ extension from C# is that I first must make SOME type of reference to the class BEFORE using the extension or it will not be recognized at all.  So, if I first call the DoCPP() as a static method, the extension works fine later.  If I make a dummy instantiation of the class, it works.  If I have no forward reference of the class, I get the same error as before and recompiling does not fix it.  It seems as if this none of this is supposed to work across the languages.

I have made a few work-arounds to get the examples to compile and run.

Note the following examples:

Extension in C#

using System;

namespace Extension_CS
   public static class CExtension_CS
   {  //in C#, the "this" keyword is the key.
      public static void DoCS(this string str)
         Console.WriteLine("CS\t{0:G}\tCS", str);

Extension in C++

 * Here is the C++ implementation.  It is the least elegant and most quirky,
 * but it works.
#pragma once
namespace System;
using namespace System::Runtime::CompilerServices;     //<-Essential
// Reference: System.Core.dll //<- Essential

namespace Extension_CPP {
       public ref class CExtension_CPP
              [Extension] // or [ExtensionAttribute] /* either works */
              static void DoCPP(String^ str)
                     Console::WriteLine("C++\t{0:G}\tC++", str);

Extension in VB



Calling program in C#

 * Main calling program
 * Intellisense and VS2008 complain about the CPP implementation, but with a
 * little duct-tape, it works just fine.
using System;
using Extension_CPP;
using Extension_CS;
using Extension_VB; // virtual namespace

namespace TestExtensions
   public static class CTestExtensions
       * For some reason, this needs a direct reference into the C++ version
       * even though it does nothing than add a null reference.
       * The constructor provides the fake usage to please the compiler.
      private static CExtension_CPP x = null;   // <-DUCT_TAPE!
      static CTestExtensions()
         // Fake usage to stop compiler from complaining
         if (null != x) {} // <-DUCT_TAPE

      static void Main(string[] args)
         string strData = "from C#";


Calling program in VB 


 Calling program in C++



// TestExtensions_CPP.cpp : main project file.

#include "stdafx.h"

using namespace System;
using namespace Extension_CPP;
using namespace Extension_CS;
using namespace Extension_VB;

void main(void)
        * Extension methods are called like static methods
        * when called from C++.  There may be a difference in
        * syntax when calling the VB extension as VB Extensions
        * are embedded in Modules instead of classes
    String^ strData = "from C++";
//since Extensions go in Modules


Imports Extension_CPP
Imports Extension_CS
Imports Extension_VB
Imports System.Runtime.CompilerServices

Module TestExtensions_VB
   <Extension()> _
Public Sub DoCPP(ByVal str As String)
'Framework does not treat this as an extension, so use the static
End Sub

   Sub Main()
Dim strData As String = "from VB"
   End Sub

' Here is the VB implementation.  This is not as elegant as the C#, but it's
' functional.
Imports System.Runtime.CompilerServices
Public Module modExtension_VB 'Extension methods can be defined only in modules.
   <Extension()> _
      Public Sub DoVB(ByVal str As String)
      Console.WriteLine("VB" & Chr(9) & "{0:G}" & Chr(9) & "VB", str)
   End Sub

posted @ Friday, March 5, 2010 5:22 PM

Comments on this entry:

# re: Cross-language Extension Method Calling

Left by James Gwinnutt at 4/26/2010 4:09 AM
Hi Tom,

Please could you clarify what the line below (in 'calling program in c#') does:

using Extension_VB; // vitual namespace

It appears to just give a 'undefined' compile-time error.

I'm trying to call a VB extension method from C#... it works fine if i invoke it using static method syntax, i.e.

Module.Function(object, various parameters..)

but for some reason the c# compiler doesn't like invoking it using extension method syntax:

Object.Function(various parameters)

... yet this syntax can be used fine in VB!

Thanks for any help you can give.

# re: Cross-language Extension Method Calling

Left by Tom at 4/26/2010 9:10 AM
James, good question!
I do not have Extension_VB set up as an actual namespace, but I've assumed because the AssemblyInfo.vb has the AssemblyTitle and/or the AssemblyProduct set to Extension_VB, then the framework somehow treats it as a namespace.

This has worked in both VS2008 Standard and VS2010 RC.

<Assembly: AssemblyTitle("Extension_VB")>
<Assembly: AssemblyProduct("Extension_VB")>

Your comment:

(not displayed)


Live Comment Preview: