当前位置:编程学习 > C#/ASP.NET >>

C-Omega 概述

答案:     摘要:Dare Obasanjo 介绍了 C-Omega 编程语言,这种语言是由 Microsoft Research 创建的,方法是增加 C# 的构造,使之能够更好地处理诸如 XML 和关系数据等信息。
  
  简介
  XML 异军突起成为信息交换的通用语言,一个主要的原因是其不同于以前的数据交换格式,XML 可以很容易地表示严格结构化的表格数据(关系数据或序列化对象)和半结构化数据(office 文档)。前者往往是强类型数据,通常使用 Object<->XML 映射技术进行处理,而后者往往是非类型化数据,通常使用传统的 XML 技术(例如 DOM、SAX 和 XSLT)进行处理。然而,在这两种情况下,开发人员使用传统的面向对象的编程语言处理 XML 时,都会感到有些脱节。
  
  在使用 Object<->XML 映射技术处理强类型 XML 的情况下,编程语言对象与 XML 架构语言(比如 DTD 或 W3C XML 架构)之间会出现“阻抗不匹配”的现象。诸如元素和属性之间的区别、文档顺序以及指定元素选择的内容模型等等,所有这些概念都是 XML 架构语言本身具有的,但在传统的面向对象编程中却没有相应的概念。将 XML 映射到对象时,这些不匹配的方面常常会导致某些歪曲和数据丢失。使用诸如 XSLT 或 DOM 这样的技术处理非类型化 XML 文档时,会出现一些不同的问题。在使用 XSLT 或其他 XML 的特定语言(比如 Xquery)的情况下,开发人员必须系统学习另一种语言,以便有效地处理 XML 以及他们所选择的编程语言。通常,主语言集成开发环境的所有好处(比如编译时检查和智能感知)都无法在处理 XML 时得到利用。在用 API(比如 DOM 或 SAX)处理 XML 的情况下,开发人员常常抱怨说,他们必须编写的代码往往变得很难使用。
  
  当用于执行特定任务的设计模式和应用程序编程接口 (API) 得到越来越广泛的使用时,它们有时会融合到编程语言中。类似 C# 的编程语言已经提升了其他语言中作为设计模式和 API 调用而存在的概念,比如本机字符串类型、使用垃圾回收的内存管理,以及该语言中针对核心构造的事件处理。现在这种演化过程已经开始涉及 XML。当 XML 变得越来越流行时,某些团体已经开始将创建和操作 XML 的构造集成到主流的编程语言中。他们期望让 XML 处理这些编程语言的本机部分,这样使用传统 XML 处理技术的开发人员所面临的一些问题将变得简单。
  
  将 XML 集成到传统编程语言中有两个最值得注意的例子,一个是由 Microsoft Research 创作的 C-Omega(C-Omega),它是 C# 的扩展;一个是由 ECMA International 创作的 ECMAScript for XML (E4X),它是 ECMAScript 的扩展。本文将概述 C-Omega 的 XML 功能,后续的文章会对 E4X 语言进行深入探索。本文首先讨论 C-Omega 中对 C# 类型系统进行的更改,接着介绍添加到 C# 语言中以使之可以更容易地处理关系数据和 XML 数据的运算符。
  
  C-Omega 类型系统
  C-Omega 类型系统的目的是,通过创建一种组合所有三种数据模型的类型系统,弥合关系数据、对象数据和 XML 数据访问之间的间隙。C-Omega 类型系统所支持的方法不是将内置 XML 或关系类型添加到 C# 语言中,而是将某些通用更改添加到 C# 类型系统中,使之更有利于对结构化的关系数据和半结构化的 XML 数据进行编程。
  
  C-Omega 中对 C# 进行的许多更改都使之更有利于对强类型 XML(特别是使用 W3C XML 架构约束的 XML)进行编程。XML 和 XML 架构中的一些概念在 C-Omega 中有相似的特征。C-Omega 中有这样一些概念,例如文档顺序、元素和属性(包含多个字段,这些字段具有相同的名称但是具有不同的值)之间的区别,以及为特定字段指定类型选择的内容模型。其中许多概念都是用传统的 Object<->XML 映射技术进行处理的,但这常常会带来很多麻烦。C-Omega 旨在使强类型 XML 编程与传统编程语言中对数组或字符串进行的编程一样简单自然。
  
  流
  C-Omega 中的流类似于 XQuery 和 XPath 2.0 以及 System.Collections.Generic.IEnumerable 类型<T>,它将存在于 .NET Framework 2.0 版中。有了流的存在,C-Omega 就可以将零个或多个项目的排序同源集合概念提升到编程语言构造中。流是 C-Omega 类型系统的基本方面,对 C# 进行的许多其他扩展都依赖于它。
  
  通过将运算符“*”追加到变量声明的类型名中声明流。通常使用迭代程序函数 生成流。迭代程序函数是一种返回值的排序序列(通过使用 yield 语句依次返回每个值)的函数。在产生值时,保持迭代程序函数的状态并允许调用方执行。当下一次调用迭代程序时,它将从上次的状态继续产生下一个值。C-Omega 中的迭代程序函数的工作方式类似于为 C# 2.0 计划的迭代程序函数。C-Omega 中的迭代程序函数与 C# 中的迭代程序函数之间最明显的区别在于,C-Omega 迭代程序返回流 (T*),而 C# 2.0 迭代程序返回枚举器 (IEnumerator)。然而,在与流或枚举器进行交互时,它们在行为上有一些细微的区别。更重要的不同在于,就像 XQuery 中的序列一样,C-Omega 中的流无法包含其他的流。相反,当组合多个流时,结果会被压缩成单一流。例如,将流 (4,5) 追加到流 (1,2,3) 中会产生一个包含 5 项的流 (1,2,3,4,5),而不是 4 项的流 (1, 2, 3, (4, 5))。虽然在 C# 2.0 中可以创建枚举器的枚举器,但是不可以用这样的方式组合多个枚举器。
  
  下面的迭代程序函数返回一个流,它包含 Lord of the Rings 三部曲中的三本书。
  
   public string* LoTR(){
  
   yield return "The Fellowship of the Ring";
   yield return "The Two Towers";
   yield return "The Return of the King";
  
   }
  
  可以使用传统的 C# foreach 循环(如下所示)处理上述函数的结果。
  
   public void PrintTrilogyTitles(){
  
   foreach(string title in LoTR())
   Console.WriteLine(title);
   }
  
  C-Omega 流强大的功能在于,可以在流中调用方法,然后将其转换为流中每一项的后续方法调用。下面的方法显示了正在使用的这种功能的示例:
  
   public void PrintTrilogyTitleLengths(){
  
   foreach(int size in LoTR().Length)
   Console.WriteLine(size);
   }
  
  以上方法调用将导致 Length 属性的值被 PrintTrilogyTitles() 方法返回的每个字符串调用。以这样一种聚合方式访问流内容属性的能力使得可以通过对象图形编写 XPath 样式的查询。
  
  还有一种应用于所有表达式 构造的概念,它使得可以将匿名方法直接应用于流的每个成员。这些匿名方法可能包含特殊变量 it,该变量被绑定到迭代流的每个连续元素。下面是 PrintTrilogyTitles() 方法(使用应用于所有表达式 构造)的替代实现。
  
   public void PrintTrilogyTitles(){
  
   LoTR().{Console.WriteLine(it)};
   }
  
  选择类型和可为空值的类型
  C-Omega 的选择类型非常类似于 C 和 C++ 编程语言中的联合类型、DTD 中的‘|’运算符,以及 W3C XML 架构中的 xs:choice 元素。下面是一个使用选择类型的类的示例:
  
  public class NewsItem{
  
   string title;
   string author;
   choice {string pubdate; DateTime date;};
   string body;
  }
  
  在这个示例中,NewsItem 类的实例可以有 System.String 类型的 pubdate 字段,也可以有 System.DateTime 类型的 date 字段,但是两者不能同时存在。应该注意到,C-Omega 编译器强制选择类型的每个字段都有不同的名称,否则在访问该字段时预定的类型会具有二义性。在 C-Omega 中访问选择类型字段的方法不同于 C 和 C++ 中的联合类型。在 C/C++ 中,编程人员必须知道特定联合类型中的值表示什么类型,因为编译器不进行静态类型检查。但编译器静态检查 C-Omega 的联合类型,这使得可以对它们进行如下声明:
  
   choice{string;DateTime;} x = DateTime.Now;
   choice{string;DateTime;} y = "12/12/2004";
  
  然而,还会有一个问题,那就是如何静态声明一个可能依赖于选择类型中并不存在的字段的类型。例如,在上面的示例中,如果用 System.DateTime 的实例初始化变量,那么 x.Length 就不是有效的属性访问,而当用字符串“12/12/2004”进行初始化时,将返回 10。这就是可为空值的类型的用武之地。
  
  在 W3C XML 架构和关系数据库领域中,所有的类型都可以有值为 null 的实例。一些语言(例如 Java)和 C# 的现有版本都不允许将 null 赋值给整型或浮点型的值类型。然而,当使用 XML 或关系数据时,能够声明 null 是某种类型的有效值非常重要。在这些情况下,不希望对值的属性访问导致引发 NullReferenceExceptions。通过将属性访问返回的所有值映射为 null 值,可为空值的类型解决了这个问题。下面是一些使用可为空值的类型的示例。
  

上一个:Visual C#编写3D游戏框架示例
下一个:利用Visual C#实现Window管道技术

CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,