Export (0) Print
Expand All

Cross-Language Interoperability

Language independence has a number of possible meanings. One meaning, which is discussed in the article Language Independence and Language-Independent Components, involves seamlessly consuming types written in one language from an app written in another language. A second meaning, which is the focus of this article, involves combining code written in multiple languages into a single .NET Framework assembly.

The following example illustrates cross-language interoperability by creating a class library named Utilities.dll that includes two classes, NumericLib and StringLib. The NumericLib class is written in C#, and the StringLib class is written in Visual Basic. Here's the source code for StringUtil.vb, which includes a single member, ToTitleCase, in its StringLib class.

Imports System.Collections.Generic
Imports System.Runtime.CompilerServices

Public Module StringLib
   Private exclusions As List(Of String) 

   Sub New()
      Dim words() As String = { "a", "an", "and", "of", "the" }
      exclusions = New List(Of String)
   End Sub

   <Extension()> _
   Public Function ToTitleCase(title As String) As String 
      Dim words() As String = title.Split() 
      Dim result As String = String.Empty

      For ctr As Integer = 0 To words.Length - 1
         Dim word As String = words(ctr)
         If ctr = 0 OrElse Not exclusions.Contains(word.ToLower()) Then
            result += word.Substring(0, 1).ToUpper() + _
            result += word.ToLower()
         End If 
         If ctr <= words.Length - 1 Then
            result += " "              
         End If    
      Return result 
   End Function 
End Module

Here's the source code for NumberUtil.cs, which defines a NumericLib class that has two members, IsEven and NearZero.

using System;

public static class NumericLib 
   public static bool IsEven(this IConvertible number)
      if (number is Byte ||
          number is SByte ||
          number is Int16 ||
          number is UInt16 || 
          number is Int32 || 
          number is UInt32 ||
          number is Int64)
         return ((long) number) % 2 == 0;
      else if (number is UInt64)
         return ((ulong) number) %2 == 0;
         throw new NotSupportedException("IsEven called for a non-integer value.");

   public static bool NearZero(double number)
      return number < .00001; 

To package the two classes in a single assembly, you must compile them into modules. To compile the Visual Basic source code file into a module, use this command:

vbc /t:module StringUtil.vb 

For more information about the command-line syntax of the Visual Basic compiler, see Building from the Command Line (Visual Basic).

To compile the C# source code file into a module, use this command:

csc /t:module NumberUtil.cs

For more information about the command-line syntax of the C# compiler, see Command-line Building With csc.exe.

You then use the Link tool (Link.exe) to compile the two modules into an assembly:

link numberutil.netmodule stringutil.netmodule /out:UtilityLib.dll /dll 

The following example then calls the NumericLib.NearZero and StringLib.ToTitleCase methods. Note that both the Visual Basic code and the C# code are able to access the methods in both classes.

using System;

public class Example
   public static void Main()
      Double dbl = 0.0 - Double.Epsilon;

      string s = "war and peace";
// The example displays the following output: 
//       True 
//       War and Peace

To compile the Visual Basic code, use this command:

vbc example.vb /r:UtilityLib.dll

To compile with C#, change the name of the compiler from vbc to csc, and change the file extension from .vb to .cs:

csc example.cs /r:UtilityLib.dll



Language Independence and Language-Independent Components

Explains how to create CLS-compliant software components that can be consumed by apps written in any language.

Common Type System

Describes how types are declared, used, and managed by the common language runtime.

Metadata and Self-Describing Components

Explains the common language runtime's mechanism for describing a type and storing that information with the type itself.

© 2014 Microsoft