面向.Net的多语言开发

最近工作需要接触了VB开发语言,但自身对VB并不熟悉,因此了解了下面向.Net的多语言开发,在此记录下。

简介

.NET 是独立的语言。 这意味着,开发人员可使用面向.NET实现的多种语言(例如C#、F#和Visual Basic)进行开发。 可访问针对 .NET 实现开发的类库的类型和成员,而不必了解它们的初始编写语言,也不必遵循任何原始语言的约定。如果你是组件开发人员,无论组件采用哪种语言,均可由任何 .NET 应用访问。(摘自微软官方文档

本文主要描述C#与VB的共同开发,其它符合CLS规范的语言类似。首先,C#与VB共同开发可以分两条路线讨论:

  1. 同一个项目中使用两种语言进行开发
  2. 同一个解决方案,不同项目使用不同语言进行开发

C#、VB共同开发

首先,两条路线都是可行的。关于1,在同一个项目中使用C#和VB开发意义不是很大,C#文件的后缀为.cs,VB文件的后缀为.vb,使用VS开发时需要进行编译设置或者手动编译,不是很方便。感兴趣的可以参考微软官方文档,本文主要介绍第二条路线。

第二条路线,即同一解决方案,不同项目分别使用C#、VB进行开发,并可以互相调用。C#和VB都是支持.Net的,都会被编译器编译为中间语言IL,这为C#、VB共同开发提供了可能。实现这个目标很简单,甚至无需任何配置,只需要创建一个解决方案,然后创建一个VB项目,一个C#项目,并添加引用,然后就可以实现互相调用。如下进行简单的测试:

class Program
{
    static void Main(string[] args)
    {
        double left = 3.5;
        double right = 4.5;
        var result = VBMath.Add(left, right);
        Console.WriteLine($"调用VB库的Add方法:{result}");

        Console.ReadLine();
    }
}

public class CSharpMath
{
    public static double Add(double left, double right) => left + right;
}
Module Program
    Sub Main(args As String())
        Dim left As Double = 3.5
        Dim right As Double = 4.5
        Dim result = CSharpMath.Add(left, right)
        Console.WriteLine("调用C# Add方法:{0}", result)

        Console.ReadLine()
    End Sub
End Module

Public Class VBMath
    Public Shared Function Add(left As Double, right As Double) As Double
        Return left + right
    End Function
End Class

上述测试成功执行,可以看出C#和VB共同开发如此简单,方便了不同语言的程序员进行联合开发。但是,C#与VB毕竟是不同的语言,有些C#的特性VB不支持,反之,VB支持的某些特性C#也不支持。比如C#区分大小写,VB不区分。修改C#的CSharpMath类,如下:

public class CSharpMath
{
    public static double Add(double left, double right) => left + right;

    public static uint TestCase = 1;
    public static uint testCase = 2;
}

在VB中进行调用:

Module Program
    Sub Main(args As String())
        ' 如下语句会报错:“TestCase”不明确,因为class“CSharpMath”中存在多种具有此名称的成员
        Console.WriteLine("测试大小写:{0}", CSharpMath.TestCase)
        Console.ReadLine()
    End Sub
End Module

此时编译器报错:“TestCase”不明确,因为class“CSharpMath”中存在多种具有此名称的成员。这时,就需要了解CLS(公共语言规范)了。下述内容摘自微软官方文档

为实现完全互操作性情景,代码中创建的所有对象都必须依赖于使用它的语言(即其调用方)的某些共性。 由于存在多种不同语言,因此 .NET 在公共语言规范 (CLS) 中指定了这些共性。 CLS 定义了许多常见应用程序所需的一组功能。对于在.NET上实现的语言,它还就语言需要支持的内容提供了一组脚本。

CLS 是 CTS 的子集。 这意味着,CTS 中的所有规则也适用于 CLS,除非 CLS 规则更严格。 如果仅使用 CLS 中的规则生成组件(即在其 API 中仅公开 CLS 功能),则将该组件视为 符合 CLS。 例如, 完全符合 CLS,因为它们需要对 .NET 支持的所有语言有效。

因此,如果需要C#与VB共同开发,需注意符合CLS规则,CLSCompliantAttribute特性可以标记元素是否符合CLS,当不符合时,编译器会发出警告。

CLSCompliantAttribute特性

CLSCompliantAttribute特性用于指示特定程序元素是否符合公共语言规范(CLS),后者定义面向 .net 的任何语言所必须支持的功能。

可以将CLSCompliantAttribute特性应用于下列程序元素:程序集、模块、类、结构、枚举、构造函数、方法、属性、字段、事件、接口、委托、参数和返回值。但是,CLS遵从性的概念仅适用于程序集、模块、类型和类型的成员,而不是成员签名的一部分。因此,CLSCompliantAttribute当应用于参数或返回值的程序元素时,将被忽略。

如果程序集标记为符合CLS,则必须使用参数标记程序集中任何不符合CLS的公开类型CLSCompliantAttribute false。 同样,如果某个类标记为符合CLS,则必须单独标记所有不符合CLS的成员。

详细内容可以参考微软官方文档。如下进行CLSCompliantAttribute特性测试:

[CLSCompliant(true)] // 程序集也需添加该特性
public class CSharpMath
{
    public static double Add(double left, double right) => left + right;

    // 如下两行代码编译器会警告:类型不符合CLS
    public static uint TestCase = 1;
    public static uint testCase = 2;
}

当然并不是所有代码都需要符合CLS,只需要将CLS符合性规则应用于组件的公共接口,私有部分不必符合规范,即可设计与语言无关的组件。

另外,多语言开发或许还有另外一个思路,就是进行代码转换。

你可能感兴趣的