Esta seção descreve o suporte interno do common language runtime para interoperabilidade de linguagem e explica a função que o CLS (Common Language Specification) tem ao ativar a garantia de interoperabilidade entre linguagens.
Consulte a partição I, “Conceitos e arquitetura”, do Standard ECMA 335: Common Language Infrastructure (CLI) Partitions I to VI, que inclui uma discussão detalhada sobre a CLS.
Interoperabilidade de linguagem é a capacidade para o código que está escrito em uma linguagem de programação específica para interagir com o código que está escrito em uma linguagem de programação diferente.
Interoperabilidade de linguagem pode ajudar a aumentar a reutilização de código e a melhorar a eficiência do processo de desenvolvimento.
Como os desenvolvedores utilizam uma ampla variedade de ferramentas e tecnologias, cada uma das quais apoiando características e tipos diferentes, foi historicamente difícil assegurar a interoperabilidade de linguagem.
Contudo, compiladores de linguagem e ferramentas que visam o benefício do Common Language Runtime beneficiam o do suporte do tempo de execução interno para interoperabilidade de linguagem.
O Common Language Runtime fornece a fundação necessária para interoperabilidade de linguagem, especificando e forçando um sistema de tipo comum e provendo metadados.
Como todas as linguagens que visam o tempo de execução seguem as regras do common type system para definir e usar tipos, o uso de tipos é consistente através de linguagens.
Metadados permitem a interoperabilidade de linguagem definindo um mecanismo uniforme para armazenar e recuperar informações sobre os tipos. Compiladores armazenam informações de tipo como metadados, e o Common Language Runtime usa essas informações para fornecer serviços durante a execução; o Runtime pode gerenciar a execução de aplicativos multilinguagem porque todas as informações de tipo são armazenadas e recuperadas da mesma maneira, independentemente do idioma que código foi escrito.
Benefícios de código gerenciados pelo suporte do Runtime para interoperabilidade de linguagem dos seguintes modos:
-
Tipos podem herdar implementação de outros tipos, passar objetos para outros tipos de métodos e chamar métodos definido em outros tipos, independentemente da linguagem em que os tipos são implementados.
-
Depuradores, criadores de perfil ou outras ferramentas são necessárias para compreender somente um ambiente - a linguagem intermediária comum (CIL) e metadados para o common language runtime - e podem suportar qualquer linguagem de programação que atinge o tempo de execução.
-
O tratamento de exceção é consistente em linguagens.
Seu código pode gerar uma exceção em um linguagem e essa exceção pode ser interceptada e compreendida por um objeto escrito em outra linguagem.
Embora o Runtime forneça todo o código dirigido do suporte para executar em um ambiente multilinguagem, não há nenhuma garantia que a funcionalidade dos tipos que você cria possa ser totalmente usada pelas linguagens de programação que outros desenvolvedores usam.
Isso ocorre, principalmente, porque cada compilador de linguagem utilizando o Runtime usa o sistema de tipos e metadados para oferecer suporte ao seu próprio conjunto exclusivo de recursos de linguagem. Em casos onde você não conhece a linguagem que o código de chamada será escrito, você dificilmente saberá se as características que o componente expõe são acessíveis para o chamador. Por exemplo, se a linguagem de escolha suporta números inteiros sem sinal, você deve criar um método com um parâmetro de tipo UInt32. No entanto, esse método seria inutilizável a partir de uma linguagem que não tenha noção de números inteiros sem sinal.
Para garantir que seu código gerenciado seja acessível pelos desenvolvedores usando outras linguagens de programação, o .NET Framework fornece o Especificação da linguagem comum (CLS), que descreve um conjunto fundamental de recursos de linguagem e define regras sobre como esses recursos são usados.
Para obter mais informações sobre compatibilidade CLS em componentes e ferramentas, consulte Escrevendo código compatível com CLS.
O exemplo a seguir ilustra a interoperabilidade de idiomas cruzados criando uma biblioteca de classes denominada Utilities.dll que inclui duas classes, NumericLib e StringLib.
A classe NumericLib é escrita em C#, e a classe StringLib é escrita em Visual Basic. A seguir está o código-fonte para StringUtil.vb, que inclui um único membro, ToTitleCase, em sua classe StringLib .
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)
exclusions.AddRange(words)
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() + _
word.Substring(1).ToLower()
Else
result += word.ToLower()
End If
If ctr <= words.Length - 1 Then
result += " "
End If
Next
Return result
End Function
End Module
A seguir está o código-fonte para NumberUtil.cs, que define uma classe de NumericLib que possui dois membros, IsEven e 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;
else
throw new NotSupportedException("IsEven called for a non-integer value.");
}
public static bool NearZero(double number)
{
return number < .00001;
}
}
Para empacotar as duas classes em um único assembly, você deve compilar em módulos.
Você compila o arquivo de código-fonte Visual Basic em um módulo com o seguinte comando:
vbc /t:module StringUtil.vb
Para obter mais informações sobre a sintaxe da linha de comando do compilador Visual Basic, consulte Construção da linha de comando (Visual Basic).
Você cria o arquivo de código-fonte C# em um módulo com o seguinte comando:
csc /t:module NumberUtil.cs
Para obter mais informações sobre a sintaxe da linha de comando do compilador C#, consulte Construção de linha de comando com CSC. exe.
Você então usa a Ferramenta de link (Link.exe) para compilar os dois módulos em um assembly:
link numberutil.netmodule stringutil.netmodule /out:UtilityLib.dll /dll
O exemplo a seguir chama os métodos NumericLib.NearZero e StringLib.ToTitleCase. Observe que o código do Visual Basic e o código do C# podem acessar os métodos em ambas as classes.
using System;
public class Example
{
public static void Main()
{
Double dbl = 0.0 - Double.Epsilon;
Console.WriteLine(NumericLib.NearZero(dbl));
string s = "war and peace";
Console.WriteLine(s.ToTitleCase());
}
}
// The example displays the following output:
// True
// War and Peace
O código Visual Basic pode ser compilado a partir da linha de comando usando o seguinte comando:
vbc example.vb /r:UtilityLib.dll
Para compilar com C#, altere o nome do compilador de vbc para csc, e altere a extensão de arquivo .vb para .cs.