.NET 和动态语言

  • Jonathan Allen
  • 张善友

2008 年 11 月 4 日

话题:.NET语言 & 开发架构

在今后的数月和数年内,动态语言将成为.NET 平台上越来越重要的角色。微软在动态语言和 CLR 之间的集成作了大量的投资。

在我们进入集成工作之前,需要花点时间来讨论一下开源。在.NET 平台上最重要的动态语言是 IronPython 和 IronRuby。这两种语言都采用的是开源协议,它们并不按照正常的计划修改语言。所有由微软支持的开源语言都有两个发布周期。针对开源项目会有发布前 / 发布的通常计划,这会有许多的展示版本。与此同时还会有正式的微软首选的进行过深入测试的版本。公司和开发人员可以选择任一种发布方式的版本,它们都是基于同样的代码。

至于集成,都是围绕着 IDynamicObject 接口。这种方法作为一个方法绑定器以允许每个对象使用的这些语言的语义。开箱即用的语言包括 IronPython,IronRuby,JScript 和 COM。是的,COM 被认为是后期绑定和动态方法调用方面的一门动态语言。

在特定的语言绑定器之外,开发人员可以在单一的类上使用特别规则。最简单的方法是从使用抽象类 DynamicObject 开始。下面是可以被重写自定义行为的动作清单。你看这个清单的时候,你会发现你所使用的语言的语法并不支持某些动作。

  • GetMember
  • SetMember
  • DeleteMember
  • UnaryOperation
  • BinaryOperation
  • Convert
  • InvokeMember
  • Invoke
  • CreateInstance
  • GetIndex
  • SetIndex
  • DeleteIndex

开发人员并不需要实现所有的这些方法。例如,它们可以只通过支持 SetMember 和 GetMember 来创建一个属性包。正是这样设计的方式,一个真正动态的类可以用任何语言来编写,甚至是像 C# 那样静态类型的语言。

IronPython 在最初是有它自己语言特定的语言抽象语法树。在 DLR 的开发过程中发现在不同语言之间的差异事实上是很小的。最后,确定 LINQ 表达式树(LINQ Expression)是任何动态语言所需要的东西。

将在.NET 4 上增加所缺少的特性是分配、流程控制(循环和 goto)以及动态调度节点。动态调度节点是语言特定和用于方法调用和重载决策的特定于语言的规则。

特定于语言语义的一个示例是 2 乘以 20 亿的结果。如果表达式树表达 IronRuby 或者 IronPython 的语义,它将返回 40 亿。使用 C# 的默认语义将会溢出以及 VB 的语义将抛出一个异常。也许想知道为什么,IronRuby 和 IronPython 在可能发生溢出的时候会自动转换 Int32 到 BigInteger。

为了提高性能,DLR 使用一种新的 call site 机制。DLR 中的 Call sites 是动态调用基于委托的静态类型化的表示。由于创建委托的开销是很大的,委托被缓存到一个列表中。对于每一个调用,从列表中找到一个匹配的。如果看到一个之前没见过的类型,一个新的基于共享抽象语法树的类型被添加到列表中。

要确定一个参数类型是否看到过,每个语言需要提供一个 MetaObject。这用于检查参数类型是否与过去所见过的类型匹配以及如果类型匹配的话如何处理。

创建新的 MetaObject 的能力允许开发人员替换掉昂贵的基于哈希表的名称,而去查找代表了被调用的方法的实际表达式树。这取决于它是如何编写的,甚至可以超过静态语言世界中所看到的性能。

查看英文原文:.NET and Dynamic Languages

.NET语言 & 开发架构