菜头粿

查看: 322|回复: 0
打印 上一主题 下一主题

C-Omega-C#的下一代语言

[复制链接]
1#
跳转到指定楼层
发表于 2009-8-29 12:15:27 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式





C-Omega-C#的下一代语言
摘要:DareObasanjo介绍了C-Omega编程语言,这种语言是由MicrosoftResearch创建的,方法是增加C#的构造,使之能够更好地处理诸如XML和关系数据等信息。  简介  XML异军突起成为信息交换的通用语言,一个主要的原因是其不同于以前的数据交换格式,XML可以很容易地表示严格结构化的表格数据(关系数据或序列化对象)和半结构化数据(office文档)。前者往往是强类型数据,通常使用Object<->XML映射技术进行处理,而后者往往是非类型化数据,通常使用传统的XML技术(例如DOM、SAX和XSLT)进行处理。然而,在这两种情况下,开发人员使用传统的面向对象的编程语言处理XML时,都会感到有些脱节。  在使用Object<->XML映射技术处理强类型XML的情况下,编程语言对象与XML架构语言(比如DTD或W3CXML架构)之间会出现“阻抗不匹配”的现象。诸如元素和属性之间的区别、文档顺序以及指定元素选择的内容模型等等,所有这些概念都是XML架构语言本身具有的,但在传统的面向对象编程中却没有相应的概念。将XML映射到对象时,这些不匹配的方面常常会导致某些歪曲和数据丢失。使用诸如XSLT或DOM这样的技术处理非类型化XML文档时,会出现一些不同的问题。在使用XSLT或其他XML的特定语言(比如Xquery)的情况下,开发人员必须系统学习另一种语言,以便有效地处理XML以及他们所选择的编程语言。通常,主语言集成开发环境的所有好处(比如编译时检查和智能感知)都无法在处理XML时得到利用。在用API(比如DOM或SAX)处理XML的情况下,开发人员常常抱怨说,他们必须编写的代码往往变得很难使用。  当用于执行特定任务的设计模式和应用程序编程接口(API)得到越来越广泛的使用时,它们有时会融合到编程语言中。类似C#的编程语言已经提升了其他语言中作为设计模式和API调用而存在的概念,比如本机字符串类型、使用垃圾回收的内存管理,以及该语言中针对核心构造的事件处理。现在这种演化过程已经开始涉及XML。当XML变得越来越流行时,某些团体已经开始将创建和操作XML的构造集成到主流的编程语言中。他们期望让XML处理这些编程语言的本机部分,这样使用传统XML处理技术的开发人员所面临的一些问题将变得简单。  将XML集成到传统编程语言中有两个最值得注意的例子,一个是由MicrosoftResearch创作的C-Omega(C-Omega),它是C#的扩展;一个是由ECMAInternational创作的ECMAScriptforXML(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(特别是使用W3CXML架构约束的XML)进行编程。XML和XML架构中的一些概念在C-Omega中有相似的特征。C-Omega中有这样一些概念,例如文档顺序、元素和属性(包含多个字段,这些字段具有相同的名称但是具有不同的值)之间的区别,以及为特定字段指定类型选择的内容模型。其中许多概念都是用传统的Object<->XML映射技术进行处理的,但这常常会带来很多麻烦。C-Omega旨在使强类型XML编程与传统编程语言中对数组或字符串进行的编程一样简单自然。 流 C-Omega中的流类似于XQuery和XPath2.0以及System.Collections.Generic.IEnumerable类型,它将存在于.NETFramework2.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中可以创建枚举器的枚举器,但是不可以用这样的方式组合多个枚举器。  下面的迭代程序函数返回一个流,它包含LordoftheRings三部曲中的三本书。publicstring*LoTR(){yieldreturn"TheFellowshipoftheRing";yieldreturn"TheTwoTowers";yieldreturn"TheReturnoftheKing";}可以使用传统的C#foreach循环(如下所示)处理上述函数的结果。publicvoidPrintTrilogyTitles(){foreach(stringtitleinLoTR())Console.WriteLine(title);}  C-Omega流强大的功能在于,可以在流中调用方法,然后将其转换为流中每一项的后续方法调用。下面的方法显示了正在使用的这种功能的示例:publicvoidPrintTrilogyTitleLengths(){foreach(intsizeinLoTR().Length)Console.WriteLine(size);}  以上方法调用将导致Length属性的值被PrintTrilogyTitles()方法返回的每个字符串调用。以这样一种聚合方式访问流内容属性的能力使得可以通过对象图形编写XPath样式的查询。  还有一种应用于所有表达式构造的概念,它使得可以将匿名方法直接应用于流的每个成员。这些匿名方法可能包含特殊变量it,该变量被绑定到迭代流的每个连续元素。下面是PrintTrilogyTitles()方法(使用应用于所有表达式构造)的替代实现。publicvoidPrintTrilogyTitles(){LoTR().{Console.WriteLine(it)};}  选择类型和可为空值的类型  C-Omega的选择类型非常类似于C和C++编程语言中的联合类型、DTD中的‘|’运算符,以及W3CXML架构中的xs:choice元素。下面是一个使用选择类型的类的示例:publicclassNewsItem{stringtitle;stringauthor;choice{stringpubdate;DateTimedate;};stringbody;}  在这个示例中,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。这就是可为空值的类型的用武之地。  在W3CXML架构和关系数据库领域中,所有的类型都可以有值为null的实例。一些语言(例如Java)和C#的现有版本都不允许将null赋值给整型或浮点型的值类型。然而,当使用XML或关系数据时,能够声明null是某种类型的有效值非常重要。在这些情况下,不希望对值的属性访问导致引发NullReferenceExceptions。通过将属性访问返回的所有值映射为null值,可为空值的类型解决了这个问题。下面是一些使用可为空值的类型的示例。string?s=null;int?size=s.Length;//returnsnullinsteadofthrowing//NullReferenceExceptionif(size==null)Console.WriteLine("ThevalueofsizeisNULL");choice{string;DateTime;}pubdate=DateTime.Now;int?dateLen=pubdate.Length;//workssinceitreturnsnullbecause//LengthisapropertyofSystem.StringintdateLen2=(int)pubdate.Length;//throwsNullReferenceException  该功能类似(但不同)于C#2.0中的可为空值的类型。C#2.0中可为空值的类型是Nullable的实例,它包含一个值和一个指示(不论指示值是否为null)。从本质上讲,这是一些值类型(比如不可为null的整型和浮点型)的包装。C-Omega采取了更进一步的措施,当访问值为null的可为空值的类型的字段或属性时,返回null,而不是引发NullReferenceException。  匿名结构匿名结构类似于W3CXML架构中的xs:sequence元素。匿名结构使得能够建模C-Omega中某些以XML为中心的概念(比如文档顺序和一个元素可能有多个名称相同但值不同的子元素的事实)。匿名结构类似于C#中的常规结构,但有几个关键的不同之处:1.匿名结构没有显式类型名。2.匿名结构中的字段是排序的,这使得可以通过数组索引运算符访问它们。3.匿名结构中的字段不必有名称。它们可以只有类型。4.匿名结构可以包含具有相同名称的多个字段。在这种情况下,通过名称访问这些字段将导致返回流。5.具有相似结构的匿名结构(即相同顺序中的相同成员类型)是兼容的,而且这种结构的变量可以来回赋值。以下示例突出显示了C-Omega中匿名结构的多种特征。struct{int;string;string;DateTimedate;string;}x=new{47,"HelloWorld","DareObasanjo",date=DateTime.Now,"Thisismyfirststory"};Console.WriteLine(x[1]);DateTimepubDate=x.date;struct{long;string;string;DateTimedate;string;}newsItem=x;Console.WriteLine(newsItem[1]+"by"+newsItem[2]+"on"+newsItem.date);struct{stringfield;stringfield;stringfield;}field3=new{field="one",field="two",field="three"};string*strField=field3.field;//stringstrField=field3.fielddoesn'tworksincefield3.fieldreturnsastreamstruct{intvalue;stringvalue;}tricky=new{value=10,value="ten"};choice{int;string;}*values=tricky.value;内容类内容类是一种使用struct关键字将其成员按不同的单元进行分组的类。在某种程度上,内容类类似于XML中的DTD。考虑下面Books对象的内容类:publicclassBooks{struct{stringtitle;stringauthor;stringpublisher;string?onloan;}*Book;}这个示例类似于下面的DTD:<!ELEMENTBooks(Book*)><!ELEMENTBook(title,author,publisher,onloan?)><!ELEMENTtitle(#PCDATA)><!ELEMENTauthor(#PCDATA)><!ELEMENTpublisher(#PCDATA)><!ELEMENTonloan(#PCDATA)>以及下面的XML架构:下面的代码示例显示了如何使用Books对象:usingMicrosoft.Comega;usingSystem;publicclassBooks{struct{stringtitle;stringauthor;stringpublisher;string?onloan;}*Book;publicstaticvoidMain(){Booksbooks=newBooks();books.Book=newstruct{title="Essential.NET",author="DonBox",publisher="Addison-Wesley",onloan=(string?)null};Console.WriteLine((string)books.Book.author+"istheauthorof"+(string)books.Book.title);}}C-Omega中的查询运算符C-Omega将两大类查询运算符添加到C#语言中:?基于XPath的运算符,用于根据名称或类型查询对象的成员变量。?基于SQL的运算符,用于执行包括一个或多个对象数据的投影、分组、联接的复杂查询。  基于XPath的运算符  有了流以及可以有名称相同的多个成员的匿名结构的存在,即使C-Omega中用“.”运算符进行的普通直接成员访问也可以认为是一种查询操作。例如,前一部分的books.Book.title操作将返回Books类中包含的所有Book对象的标题。这等效于XPath查询'/Books/Book/title',它返回包含在Books元素中的Book元素的所有标题。    通配符成员访问运算符“.*”可以用于检索某种类型的所有字段。该运算符等效于XPath查询child::*,它返回当前节点的主要节点类型的所有子节点。例如,操作books.Book.*返回一个流容器,所有Book对象的所有成员都包含在Books类中。这等效于XPath查询'/Books/Book/*',它返回Books元素中包含的Book元素的所有子元素。  C-Omega还支持使用“...”运算符的可传递成员访问,这类似于XPath中的descendent-or-self轴或“//”缩写路径。操作books...title以递归方式返回一个流,其中包含Books类(或者其任何内容的成员字段)中包含的所有title成员字段。这等效于XPath查询'/Books//title',它返回所有的title元素(它们是Books元素的子代)。也可以使用可传递成员访问运算符匹配以'...typename::*'形式的语法将其限制于特定类型的节点。例如,操作books...string::*以递归方式返回一个流,它包含Books类(或者其任何内容的成员字段)中包含的System.String类型的所有成员字段。这类似于XPath2.0查询/Books//element(*,xs:string),它匹配xs:string类型的Books元素的任何子代。  筛选操作可以以相同方式应用于可传递成员访问的结果,谓词可以用于筛选XPath查询。与在XPath中一样,可以使用放置在查询后的'[expression]'运算符将C-Omega筛选器应用于查询操作。正如应用于所有表达式这种情况,筛选器可以包含特殊变量it,该变量被绑定到迭代流的每个连续元素。下面是一个示例,它查询匿名结构中System.Int32类型的所有字段,然后筛选其值大于8的结果。struct{inta;intb;intc;}z=new{a=5,b=10,c=15};int*values=z...int::*[it>8];foreach(intiinvalues){Console.WriteLine(i+"isgreaterthan8");}


高级模式
B Color Image Link Quote Code Smilies

本版积分规则

手机版|Archiver| 菜头粿 声明:本站所发贴子内容仅代表网友观点,不代表本站立场,严禁一切与国家法律相抵触的内容。感谢关注!
粤icp备19073828

GMT+8, 2026-7-26 15:44 , Processed in 0.107596 second(s), 15 queries .

粤东.中国

© 2007-2026 czczcz.com

快速回复 返回顶部 返回列表