面向.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 ModulePublic 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符合性规则应用于组件的公共接口,私有部分不必符合规范,即可设计与语言无关的组件。
【面向.Net的多语言开发】另外,多语言开发或许还有另外一个思路,就是进行代码转换。

    推荐阅读