.net

    .NET 是 Microsoft XML Web services 平台。XML Web services 允许应用程序通过 Internet 进行通讯和共享数据,而不管所采用的是哪种操作系统、设备或编程语言。Microsoft .NET 平台提供创建 XML Web services 并将这些服务集成在一起之所需。对个人用户的好处是无缝的、吸引人的体验。

目录

基本概要
应用组件客户端应用
WebService
接口规范
CLR 与 CIL
.NET之历史脚步
.NET之一路走来动态编程
并行计算
协变和逆变
命名参数和可选参数
.NET3.0新特性隐式类型化本地变量
匿名类型
隐式类型化数组
对象构造者
集合构造者
Lambda表达式
扩展方法
Linq查询表达式
.NET3.5新特性快速指南
语言改进和LINQ
其他改进
注意事项
加密处理安全威胁
加密前提
工具概况
加密/解密
防止破解
.NET之未来发展
常见的域名后缀基本概要
应用组件 客户端应用
WebService
接口规范
CLR 与 CIL
.NET之历史脚步
.NET之一路走来 动态编程
并行计算
协变和逆变
命名参数和可选参数
.NET3.0新特性 隐式类型化本地变量
匿名类型
隐式类型化数组
对象构造者
集合构造者
Lambda表达式
扩展方法
Linq查询表达式
.NET3.5新特性 快速指南
语言改进和LINQ
其他改进
注意事项
加密处理 安全威胁
加密前提
工具概况
加密/解密
防止破解
.NET之未来发展
常见的域名后缀展开 基本概要
  .NET就是微软的用来实现XML,Web Services, SOA(面向服务的体系结构service-oriented architecture)和敏捷性的技术。对技术人员,想真正了解什么是.NET,必须先了解.NET技术出现的原因和它想解决的问题,必须先了解为什么他们需要XML, Web Services 和 SOA。技术人员一般将微软看成一个平台厂商。微软通过技术平台,而技术人员在这个技术平台之上创建应用系统。从这个角度,.NET也可以如下来定义:.NET是微软的新一代技术平台,为敏捷商务构建互联互通的应用系统,这些系统是基于标准的,联通的,适应变化的,稳定的和高性能的。 从技术的角度,一个.NET应用是一个运行于.NET Framework之上的应用程序。(更精确的说,一个.NET应用是一个使用.NET Framework类库来编写,并运行于公共语言运行时 Common Language Runtime之上的应用程序。)如果一个应用程序跟.NET Framework无关,它就不能叫做.NET程序。比如,仅仅使用了XML并不就是.NET应用,仅仅使用SOAP SDK调用一个Web Service也不是.NET应用。
应用组件
客户端应用
  组成.net软件技术的组件,组件之一,“智能”客户端应用软件和操作系统,包括PC、PA、手机或其他移动设备通过互联网、借助Web Services技术,用户能够在任何时间、任何地点都可以得到需要的信息和服务。例如:可以在手机上阅读新闻、定购机票、浏览在线相册等等。现在我们假设一种场景,如公司内使用的CRM系统,应用了.NET的解决方案后所有的业务人员便可以通过手机或PDA直接访问客户信息了。
WebService
  Web Services是智能终端软件的基础,微软为用户创建智能终端提供了一整套丰富的解决方案,包括:   .NET Framework - 智能终端实现跨平台(设备无关性)的执行环境   Visual Studio .NET – 建立并集成Web Services和应用程序的快速开发工具   Microsoft Windows Server 2003 – 新一代的企业服务器,用于提供建立和发布各种解决方案   Microsoft Office Professional Edition 2003 – 内建的工具集也能帮助开发智能终端   现在  .net
发展最快的终端非手机莫属了,有两大阵营在开发SmartPhone技术,一个是微软为代表的Stinger应用于三星,另一个就是以NOKIA、爱立信组成的Symbian。   Web Services是.NET的核心技术。那什么是Web Services呢?正如Web是新一代的用户与应用交互的途径,XML是新一代的程序之间通讯的途径一样,Web Services是新一代的计算机与计算机之间一种通用的数据传输格式,可让不同运算系统更容易进行数据交换。Web Services有以下几点特性:Web services允许应用之间共享数据;Web services分散了代码单元;基于XML这种internet数据交换的通用语言,实现了跨平台、跨操作系统、跨语言。那微软的ASP和Web services究竟有什么不同呢,ASP仍然是一个集中式计算模型的产物,只不过是披着一层互联网的外衣。但Web Services却是一个迥然不同的精灵,它秉承“软件就是服务”的真言,同时顺应分布式计算模式的潮流。而它的存在形式又与以往软件不同。这种组件模式,小巧、单一,对于开发人员来讲,开发成本较低。   在这里指出Web services不是微软发明的,同样也不属于微软专有。Web services是一个开放的标准,和HTTP、 XML、SOAP一样。他们是一个工业标准而非微软标准,WS-I是为了促进Web Services互通性的联盟组织,最初是由IBM和微软所发起,其它的成员包括BEA System、惠普计算机(HP)、甲骨文(Oracle)、英特尔(Intel)和SUN 计算机(Sun Microsystem)。如今网络上存在的大多Web services其实没有使用.NET构架,Web services具有互操作属性,你同样可以使用Windows开发客户端来调用运行于Linux上面的Web services的方法。
接口规范
  先前  microsoft .net
提到的接口规范问题,在.NET中,Web service接口通常使用Web Services Description Language (WSDL)描述。 WSDL 使用XML来定义这种接口操作标准及输入输出参数,看起来很像COM和CORBA的接口定义语言(IDLS)Interface Definition Languages。接口定义后就必须使用一些协议调用接口,如SOAP协议,SOAP源于一种叫做XML RPC(XML远程进程调用remote procedure calling)的协议,而Java则根据XML-RPC发展了自己的JAX-RPC协议用来调用Web Services。发布和访问Web Services的接口就用到UDDI了,这里我们只需要知道WSDL使用XML定义Web Services接口,通过SOAP访问Web Services,在internet上寻找Web Services使用UDDI就行了,更多的Web Services将在最后一课介绍。服务器架构——Microsoft Windows Server System Microsoft提供了最佳的服务器构架—Microsoft Windows Server System—便于发布、配置、管理、编排Web Services。为了满足分布式计算的需要微软构造了一系列的服务器系统,这些内建安全技术的系统全部支持XML,这样加速了系统、应用程序以及同样使用Web Services的伙伴应用之间的集成。   Microsoft Windows Server System包括:   Microsoft Application Center 2000 - 配置和管理Web应用程序   Microsoft BizTalk Server 2002 - 建立基于XML的跨应用和组织的商业逻辑     visual studio .net
Microsoft Commerce Server 2002 – 能够迅速建立大规模电子商务的解决方案   Microsoft Content Management Server 2002 – 管理动态电子商务网站的目录   Microsoft Exchange Server 2000 – 用于进行随时随地的通讯协作   Microsoft Host Integration Server 2000 – 用于和主机系统之间传输数据   Microsoft Internet Security and Acceleration Server 2000 (ISA Server) – internet连接   Microsoft Mobile Information Server 2002 – 用于支持手持设备   Microsoft Operations Manager 2000 – 描述企业级解决方案的操作管理   Microsoft Project Server 2002 - 提供项目管理的最佳方案   Microsoft SharePoint Portal Server 2001 – 查询、共享、发布商业信息   Microsoft SQL Server 2000 – 企业级数据库   Microsoft Visual Studio .NET和Microsoft .NET Framework对于建立,发布并运行Web Services是一个完美的解决方案。   Microsoft .Net 框架 SDK 快速入门教程:www.aspxweb.com/quickstart/   微软官方的教程。
CLR 与 CIL
  .NET的  NET Framework 环境
初级组成是CIL和CLR。CIL是一套运作环境说明,包括一般系统、基础类库和与机器无关的中间代码,全称为通用中间语言(CIL)。CLR则是确认操作密码符合CIL的平台。在CIL执行前,CLR必须将指令及时编译转换成原始机械码。   所有CIL(通用中间语言)都可经由.NET自我表述。CLR检查元资料以确保正确的方法被调用。元资料通常是由语言编译器生成的,但开发人员也可以通过使用客户属性创建他们自己的元资料。   如果一种语言实现生成了CIL,它也可以通过使用CLR被调用,这样它就可以与任何其他.NET语言生成的资料相交互。CLR也被设计为作业系统无关性。   当一个汇编体被载入时,CLR执行各种各样的测试。其中的两个测试是确认与核查。在确认的时候,CLR检查汇编体是否包含有效的元资料和CIL,并且检查内部表的正确性。核查则不那么精确。核查机制检查代码是否会执行一些“不安全”的操作。核查所使用的演算法非常保守,导致有时一些“安全”的代码也通不过核查。不安全的代码只有在汇编体拥有“跳过核查”许可的情况下才会被执行,通常这意味着代码是安装在本机上的。   通过.NET,你可以用SOAP和不同的Web services进行交互。
.NET之历史脚步
  作为.NET平台下的静态强类型语言,在过去10年的发展历程中披荆斩棘,已经逐渐成为应用开发语言中的佼佼者。从TIOBE开发语言排行榜的最新统计来看,C#位居第六成为开发语言市场的顶级产品:   (注:此为2008年12月的TIOBE开发语言排行榜,参考2008年12月编程语言排行榜:C/C++有望夺得"年度语言")   因此,在我们讲解历史的开始,将C#发展历史中的里程碑作以标记,来感受一下C# 10年的发展历程,为每开发者在心底搭起一座通往未来的桥梁。   2000年之夏,微软大当家——盖茨先生着手战略调整,微软大刀阔斧的进行了技术改革与创新,并由此为世界带来一个新的名词,这就是.NET。那么什么是.NET呢?在.NET这一概念诞生之初,这一概念连微软本身都充满了定位的错乱和迷茫,以至于一时之间处处皆为.NET,大有一统江湖之势。随着.NET平台的逐渐完善,概念和定位上的混乱已经日渐清晰,作为这场变革中的一项重要内容,一种全新的、能够适应.NET平台特性的高级语言C#也随之诞生。这一任务理所当然的落在了Anders Hejlsberg的身上,作为Delphi之父,大师级的Anders从1998年11月开始领导了他的小组为这个世界带来全新的语言宠儿,这就是:C#。   初出茅庐的C#,就像羞羞答答的小姑娘,步步留心、时时在意,学着他人的模样,生怕在前辈面前丢脸。当她以全新的姿态出现在万千程序开发者眼前时,其兼取百家之长、优雅简洁之态、摒弃复杂之弊的特性,立时令所有的观望折服。在迎来所有目光的关注的同时,迅速成为高级语言战场的骄子。   那么,C#诞生之初兼取百家之长,具体都有哪些优秀品质呢,总结起来主要体现在两个方面包括:   · 面向对象编程。C#实现对属性、事件、委托、方法、索引器、构造器的全面支持,为面向对象的封装、继承、多态和接口提供了语言级别的支持。以继承为例,c#支持单实现继承和多接口继承,摒弃了C++中多继承带来的复杂性。   · 跨平台运行时支持。CLR是.NET平台下应用程序的通用语言运行时,是C#程序赖以生存的跨平台环境,因此C#具有了.NET平台语言的所有优势,通用类型系统、自动内存管理、统一异常处理、完全的FCL访问权,都成为C#无与伦比的优势所在。
.NET之一路走来
  无论如何,.NET 4.0已经在叩开新年的大门之时,以高调的姿态迎来一片掌声。广大的技术爱好者不会等待太长的时间,就能感受C#发展中的又一次变革。随着.NET 4.0在2009年的发布,我们对于C# 4.0的关注也将与日俱增。总体而言,C# 4.0的重头戏主要着眼在以下几个方面:   · 动态编程   · 并行计算   · 后期绑定   · 协变与逆变   废话少说,接下来我们一一领略C# 4.0中的语言特性。
动态编程
  众所周知,C#是静态强类型语言。而在很多情况下,提供“动态”行为,是常常发生的事情,例如通过反射在运行时访问.NET类型、调用动态语言对象、访问COM对象等,都无法以静态类型来获取。因此, C# 4.0引入的又一个全新的关键字dynamic,也同时引入了改善静态类型与动态对象的交互能力,这就是动态查找(Dynamic Lookup)例如:   public static void Main() {   dynamic d = GetDynamicObject();   d.MyMethod(22); // 方法调用   d.A = d.B; // 属性赋值   d[“one”] = d[“two”]; // 索引器赋值   int i = d + 100; // 运算符调用   string s = d(1,2); // 委托调用   }   就像一个object可以代表任何类型,dynamic使得类型决断在运行时进行,方法调用、属性访问、委托调用都可动态分派。同时,动态特性还体现在构建一个动态对象,在C# 4.0实现IDynamicObject接口的类型,可以完全定义动态操作的意义,通过将C#编译器作为运行时组件来完成由静态编译器延迟的操作,例如:   dynamic d = new Foo();   string s;   d.MyMethod(s, 3, null);   在具体执行过程中,C#的运行时绑定器基于运行时信息,通过反射获取d的实际类型Foo,然后在Foo类型上就MyMethod方法进行方法查找和重载解析,并执行调用,这正是动态调用的背后秘密:DLR。在.NET 4.0中将引入重要的底层组件DLR(Dynamic Language Runtime,动态语言运行时),除了实现动态查找的基础支持,DLR也同时作为基础设施为类似于IronRuby、IronPython这样的动态语言提供统一的互操作机制。总而言之,动态编程将为C#在以下领域产生巨大的变革:   · Office编程与其他COM交互。   · 动态语言支持,在C#中消费IronRuby动态语言类型将并非难事,体验动态语言特性指日可待。   · 增强反射支持。   以调用IronRython为例,我们只需引入IronPython.dll, IronPython.Modules.dll, and Microsoft.Scripting.dll,即可通过创建ScriptRuntime在C#中HostingIronPython环境,进而来操作动态语言的类型信息。   ScriptRuntime py = Python.CreateRuntime();   dynamic mypy = py.UseFile("myfile.py");   Console.WriteLine(mypy.MyMethod("Hello"));   虽然从微软当前提供的技术资料和CTP演示中,动态查找还存在或多或少的问题,但是在“动态”大行其道的今天,我们无法回避也必须拥抱这个未来的主角,因为我坚信明天会更好。
并行计算
  并行计算的出现,是计算机科学发展的必然结果,随着计算机硬件的迅猛发展,在多核处理器上工作已经是既存事实,而传统的编程模式必须兼容新的硬件环境才能使计算机性能达到合理的应用效果。用Anders大师的话说:未来5到10年,并行计算将成为主流编程语言不可忽视的方向,而4.0为C#打响了实现并发的第一枪。   未来的.NET Framework 4.0中将集成TPL(Task Parallel Library)和PLINQ(Parallel LINQ),这也意味着未来我们可以应用C# 4.0实现并行化应用,在统一的工作调度程序下进行硬件的并行协调,这将大大提高应用程序的性能同时降低现存并发模型的复杂性。   那么,我们应该一睹为快应用C#武器来开发并发环境下的超酷感受,在System.Threading.Parallel 静态类提供了三个重要的方法For、Foreach、Invoke可以为我们小试牛刀:   //应用TPL,执行并行循环任务   Parallel.For(0, 10, i =>   {   DoSomething(i);   });   在线程争用执行情况下,相同的操作在双核平台下运行,以StopWatch进行精确时间测试,并行环境下的执行时间为 2001ms,而非并行环境下的执行时间为4500ms,并行运算的魅力果然名不虚传。我们再接再厉应用PLINQ执行对于并行运算的查询、排序等,当前PLINQ支持两种方式ParallelEnumerable类和ParallelQuery类,例如:   int[] data = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };   int[] selected = (from x in data.AsParallel()   select x + 1).ToArray();   更详细的对比示例留待读者在实践中对此进行讨论,并行计算为托管代码在多核环境下的性能优化提供了统一的解决方案,而未来我们会做的更好。   备注:实际上,我们可以选择下载安装Microsoft Parallel Extensions to the .NET Framework 3.5June 2008 CTP包,就可以在.NET 3.5环境下体验并行计算的无穷魅力。
协变和逆变
  协变和逆变,是为解决问题而生的。而要理清解决什么样的问题,需要首先从理清几个简单的概念开始。首先我们进行一点操作:   Derived d = new Derived();   Base b = d;   Derived类型继承自Based类型,由Derived引用可以安全的转换为Based引用,而这种转换能力可以无缝的实现在Derived数组和Base数组,例如:   Derived[] ds = new Derived[5];   Base[] bs = ds;   而这种原始转换(由子类转换为父类)方向相同的可变性,被称为协变(covariant);其反向操作则被称为逆变(contravariant)。当同样的情形应用于泛型时,例如:   List<Derived> ds = new List<Derived>();   List<Base> bs = ds;   类似的操作却是行不通的。所以,这就成为C# 4.0中完善的问题——泛型的协变与逆变:   List<Base> bs = new List<Base>(); List<Derived> ds = new List<Derived>();   bs = ds; //List<T>支持对T协变   ds = bs; //List<T>支持对T逆变   而在C# 4.0中,伴随着协变与逆变特性的加入,C#引入两个in和out关键字来解决问题。   public interface ICovariant<out T> {   T MyAction();   }   public interface IContravariant<in T>   {   void MyAction(T arg);   }   其中,out表示仅能作为返回值的类型参数,而in表示仅能作为参数的类型参数,不过一个接口可以既有out又有in,因此既可以支持协变、支持逆变,也可以同时支持,例如:   public interface IBoth<out U, in V>   {   }
命名参数和可选参数
  命名参数和可选参数是两个比较简单的特性,对于熟悉其他编程语言的开发者来说可选参数并不陌生,为参数提供默认值时就是可选参数:   public void MyMethod(int x, int y = 10, int z = 100) {   }   因此,我们可以通过调用MyMethod(1)、MyMethod(1, 2)方式来调用MyMethod方法。而命名参数解决的是传递实参时,避免因为省去默认参数造成的重载问题,例如省去第二个参数y调用时,即可通过声明参数名称的方式来传递:   MyMethod(20, z: 200);   相当于调用MyMethod(20, 10, 200),非常类似于Attribute的调用方式。虽然只是小技巧,但也同时改善了方法重载的灵活性和适配性,体现了C#语言日趋完美的发展轨迹。   当然,除此之外.NET 4.0还增加了很多值得期待的平台特性,也将为C#编码带来前所未有的新体验。   以上相关版权归作者。
.NET3.0新特性
隐式类型化本地变量
  这个特性非常简单,有些JavaScript的影子,我们可以统一使用使用"var"关键字来声明局部变量,而不再需要指明变量的确切类型了,变量的确切类型可通过声明变量时的初始值推断出来。这样一来,可以大大简化我们声明局部变量的工作量了,下面是一个例子:   class LocalVariables : AppRunner.AbstractApplication   {   public override void Run()   {   var intValue = 5;   var stringValue = "This is a string";   var customClass = new LocalVariables();   var intArray = new int[3] { 1, 2, 3 };   foreach (var value in intArray)   Console.WriteLine(value);   }   }   上面的代码将被解析成:   class LocalVariables : AppRunner.AbstractApplication   {   public override void Run()   {   int intValue = 5;   string stringValue = "This is a string";   LocalVariables customClass = new LocalVariables();   int[] intArray = new int[3];   foreach (int value in intArray)   Console.WriteLine(value);   }   }   要特别注意的是,由于变量的类型是通过变量初始值推断而来的,所以在声明变量的同时必需为变量指定初始值。并且,变量并不是没有类型的,变量一旦初始化之后,类型就确定下来了,以后就只能存储某种类型的值了,比如上面的stringValue的类型经推断为string,所以该变量就只能保存string类型的值了。
匿名类型
  有些时候我们需要临时保存一些运算的中间结果,特别是当这些中间结果是由多个部份组成时,我们常常会去声明一个新的类型,以方便保存这些中间结果。表面上看起来这很正常,而细想之后就会发现,这个新类型只服务于这个函数,其它地方都不会再使用它了,就为这一个函数而去定义一个新的类型,确实有些麻烦。   现在,C#3.0中的匿名类型特性就可以很好的解决上面提到的问题,通过匿名类型,我们可以简单使用new { 属性名1=值1, 属性名2=值2, ..... , 属性名n=值n }的形式直接在函数中创建新的类型,看下面这个例子:   class AnonymousType : AppRunner.AbstractApplication   {   public override void Run()   {   var anonymousType1 = new {   CardNumber = "10001", Name = "van’s", Sex = true   };   Console.WriteLine(anonymousType1.CardNumber);   Console.WriteLine(anonymousType1.Name);   var anonymousType2 = new {   CardNumber = "10002", Name = "martin", Sex = true   };   anonymousType2 = anonymousType1;   }   }   在新类型中只能有字段成员,而且这些字段的类型也是通过初值的类型推断出来的。如果在声明新的匿名类型时,新类型的字段名、顺序以及初始值的类型是一致的,那么将会产生相同的匿名类型,所以上例中anonymousType1和anonymousType2的类型是相同的,自然能进行anonymousType2=anonymousType1的赋值。
隐式类型化数组
  这个特性是对隐式类型化本地变量的扩展,有了这个特性,将使我们创建数组的工作变得简单。我们可以直接使用"new[]"关键字来声明数组,后面跟上数组的初始值列表。在这里,我们并没有直接指定数组的类型,数组的类型是由初始化列表推断出来的。   class AnonymousTypeArray : AppRunner.AbstractApplication   {   public override void Run()   {   var intArray = new[] { 1, 2, 3, 4, 5 };   var doubleArray = new[] { 3.14, 1.414 };   var anonymousTypeArray = new[] {   new { Name="van’s", Sex=false, Arg=22 },   new { Name="martin", Sex=true, Arg=23 }   };   Console.WriteLine(intArray);   Console.WriteLine(doubleArray);   Console.WriteLine(anonymousTypeArray[0].Name);   }   }   上面的代码中,anonymousTypeArray变量的声明同时运用了隐式类型化数组和匿名类型两种特性,首先创建匿名类型,然后再初始值列表,推断出数组的确切类型。
对象构造者
  我们在声明数组时,可以同时对其进行初始化,这样就省去了很多麻烦,但是在创建类的对象时,这招可就不灵了,我们要么调用该类的构造函数完成对象的初始化,要么就手工进行初始化。这两种方法都不太方便,使用构造函数来对对象进行初始化时,我们为了某种灵活性,可能需要编写构造函数的多个重载版本,实在是麻烦。   C#3.0中加入的对象构造者特性,使得对象的初始化工作变得格外简单,我们可以采用类似于数组初始化的方式来初始化类的对象,方法就是直接在创建类对象的表达式后面跟上类成员的初始化代码。具体示例如下:   class Point   {   public int X { get; set; }   public int Y { get; set; }   public override string ToString()   {   return "(" + X.ToString() + ", " + Y.ToString() + ")";   }   }   class Rectangle   {   public Point P1 { get; set; }   public Point P2 { get; set; }   public Rectangle()   {   P1 = new Point();   P2 = new Point();   }   public override string ToString()   {   return "P1: " + P1 + ", P2: " + P2;   }   }   class ObjectBuilder : AppRunner.AbstractApplication   {   public override void Run()   {   Point thePoint = new Point() { X = 1, Y = 2 };   Console.WriteLine("Point(X, Y) = ", thePoint);   Rectangle theRectangle = new Rectangle() {   P1 = { X = 1, Y = 1 }, P2 = { X = 100, Y = 200 }   };   Console.WriteLine(theRectangle);   }   }   我们在定义Point类的X和Y属性时,只须写上该属性的get和set访问器声明,C#编译器会自动为我们生成默认的get和set操作代码,当我们需要定义简单属性时,这个特性非常有用。   我们以new Point() { X = 1, Y = 2 }语句,轻松的完成了对Point类的初始化工作。在创建类的对象时,我们可以按照需要去初始化类的对象,只要在类的创建表达式后跟上要初始化属性的列表即可,且可以只对需要初始化的属性赋初值,而无需把所有属性的初始值都写上去。   在theRectangle对象的初始化表达式中,我们首先对P1属性进行初始化,然而P1属性也是一个自定义的类型,所以P1属性的初始化是另一个类型(Point)的初始化表达式,我们可以这样的方式来对更加复杂的类型进行初始化。   上篇文章中介绍了C# 3.0中比较简单的四个特性,分别是隐式类型化本地变量、匿名类型、隐式类型化数组,以及对象构造者,下面我将对C# 3.0中的较复杂,同时也是非常强大的几个特性进行介绍,供大家快速浏览。
集合构造者
  我们可以在声明数组的同时,为其指定初始值,方法是直接在数组声明的后面跟上初始值列表。这样就使数组的初始化工作变得简单,而对于我们自己创建的集合类型,就无法享受到与普通数组一样的待遇了,我们无法在创建自定义集合对象的同时,使用数组的初始化语法为其指定初始值。   C# 3.0中加入的集合构造者特性,可使我们享受到与普通数组一样的待遇,从而在创建集合对象的同时为其指定初始值。为了做到这一点,我们需要让我们的集合实现ICollection<T>接口,在这个接口中,完成初始化操作的关键在于Add函数,当我使用初始化语法为集合指定初始值时,C#编译器将自动调用ICollection<T>中的Add函数将初始列表中的所有元素加入到集合中,以完成集合的初始化操作。使用示例如下:   class CollectionInitializer : AppRunner.AbstractApplication   {   class StringCollection : ICollection<string>   {   public void Add(string item)   {   Console.WriteLine(item);   }   // Other ICollection<T> Members   }   public override void Run()   {   StringCollection strings = new StringCollection() { "Van's", "Brog", "Vicky" };   }   }   在这个示例中,编译器会自动为strings对象调用Add方法,以将初始值列表中的所有元素加入到集合中,这里我们只是简单将初始值列表中的元素输出到控制台。
Lambda表达式
  C# 2.0中加入的匿名代理,简化了我们编写事件处理函数的工作,使我们不再需要单独声明一个函数来与事件绑定,只需要使用delegate关键字在线编写事件处理代码。   而C# 3.0则更进一步,通过Lambda表达式,我们可以一种更为简洁方式编写事件处理代码,新的Lambda事件处理代码看上去就像一个计算表达式,它使用"=>"符号来连接事件参数和事件处理代码。我可以这样写:SomeEvent += 事件参数 => 事件处理代码;下面是完整的示例:   delegate T AddDelegate<T>(T a, T b);   class LambdaExpression : AppRunner.AbstractApplication   {   public static event EventHandler MyEvent;   public override void Run()   {   MyEvent += delegate(object s, EventArgs e)   {   Console.WriteLine(s);   };   MyEvent += (s, e) => { Console.WriteLine(s); };   MyEvent(this, null);   AddDelegate<string> add = (a, b) => a + b;   Console.WriteLine(add("Lambda", "Expression"));   }   }   在上面的例子中,分别使用了匿名代理和Lambda表达式来实现同样的功能,可以明显看出Lambda表达式的实现更为简洁。我们在使用Lambda表达式编写事件处理代码时,无需指明事件参数的类型,且返回值就是最后一条语句的执行结果。
扩展方法
  当我们需要对已有类的功能进行扩展时,我们通常会想到继承,继承已有类,然后为其加入新的行为。而C# 3.0中加入的扩展方法特性,则提供了另一种实现功能扩展的方式,我们可以在不使用继承的前提下实现对已有类本身的扩展,这种方法并不会产生新的类型,而是采用向已有类中加入新方法的方式来完成功能扩展。   在对已有类进行扩展时,我们需将所有扩展方法都写在一个静态类中,这个静态类就相当于存放扩展方法的容器,所有的扩展方法都可以写在这里面。而且扩展方法采用一种全新的声明方式:public static 返回类型 扩展方法名(this 要扩展的类型 sourceObj [,扩展方法参数列表]),与普通方法声明方式不同,扩展方法的第一个参数以this关键字开始,后跟被扩展的类型名,然后才是真正的参数列表。下面是使用示例:   static class Extensions   {   public static int ToInt32(this string source)   {   return Int32.Parse(source);   }   public static T[] Slice<T>(this T[] source, int index, int count)   {   if (index < 0 || count < 0 || index + count > source.Length)   {   throw new ArgumentException();   }   T[] result = new T[count];   Array.Copy(source, index, result, 0, count);   return result;   }   }   class ExtensionMethods : AppRunner.AbstractApplication   {   public override void Run()   {   string number = "123";   Console.WriteLine(number.ToInt32());   int[] intArray = new int[] { 1, 2, 3 };   intArray = intArray.Slice(1, 2);   foreach (var i in intArray)   Console.WriteLine(i);   }   }   在上面的示例中,静态的Extensions类中有两个扩展方法,第一个方法是对string类的扩展,它为string类加入了名为ToInt32的方法,该方法没有参数,并返回一个int类型的值,它将完成数字字符向整数的转换。有了这个扩展方法之后,就可对任意string类的对象调用ToInt32方法了,该方法就像其本身定义的一样。   第二个扩展方法是一个范型方法,它是对所有数组类型的扩展,该方法完成数组的切片操作。   C# 3.0中的Linq表达式,就是大量运用扩展方法来实现数据查询的。
Linq查询表达式
  C# 3.0中加入的最为复杂的特性就是Linq查询表达式了,这使我们可直接采用类似于SQL的语法对集合进行查询,这就使我们可以享受到关系数据查询的强大功能。   Linq查询表达式是建立在多种C# 3.0的新特性之上的,这也是我为什么最后才介绍Linq的原因。下面看一个例子:   class LinqExpression : AppRunner.AbstractApplication   {   public override void Run()   {   // 定义匿名数组persons, 并为其赋初值   var persons = new[] {   new { Name="Van's", Sex=false, Age=22 },   new { Name="Martin", Sex=true, Age=30 },   new { Name="Jerry", Sex=false, Age=24 },   new { Name="Brog", Sex=false, Age=25 },   new { Name="Vicky", Sex=true, Age=20 }   };   /*   执行简单Linq查询   检索所有年龄在24岁以内的人   查询结果放在results变量中   results变量的类型与数组persons相同   */   var results = from p in persons   where p.Age <= 24   select p;   foreach (var person in results)   {   Console.WriteLine(person.Name);   }   Console.WriteLine();   // 定义匿名数组customers, 并为其赋初值   // 该数组是匿名类型的   var customers = new[] {   new {   Name="Van's", City="China", Orders=new[] {   new {   OrderNo=0,   OrderName="C# Programming Language(Second Edition)",   OrderDate=new DateTime(2007,9, 5)   },   new {   OrderNo=1,   OrderName="Head First Design Patterns(Chinese Edition)",   OrderDate=new DateTime(2007,9,15)   },   new {   OrderNo=2,   OrderName="ASP.NET Unleashed 2.0(Chinese Edition)",   OrderDate=new DateTime(2007,09,18)   },   new {   OrderNo=3,   OrderName="The C++ Programming Langauge(Special Edition)",   OrderDate=new DateTime(2002, 9, 20)   }   }   },   new {   Name="Brog", City="China", Orders=new[] {   new {   OrderNo=0,   OrderName="C# Programming Language(Second Edition)",   OrderDate=new DateTime(2007, 9, 15)   }   }   },   new {   Name="Vicky", City="London", Orders=new[] {   new { OrderNo=0,   OrderName="C++ Programming Language(Special Edition)",   OrderDate=new DateTime(2007, 9, 20)   }   }   }   };   /*   执行多重Linq查询   检索所在城市为中国, 且订单日期为2007年以后的所有记录   查询结果是一个匿名类型的数组   其中包含客户名, 订单号, 订单日期, 订单名四个字段   */   var someCustomers = from c in customers   where c.City == "China"   from o in c.Orders   where o.OrderDate.Year >= 2007   select new { c.Name, o.OrderNo, o.OrderDate, o.OrderName };   foreach (var customer in someCustomers)   {   Console.WriteLine(   customer.Name + ", " + customer.OrderName + ", " +   customer.OrderDate.ToString("D")   );   }   }   }   从上面的例子中,我们可以看到Linq查询的强大特性,它允许我们进行简单查询,或者进行更为复杂的多重连接查询。且查询的结果还可以是自定义的匿名类型。
.NET3.5新特性
快速指南
  VS 2008的多定向支持   VS 2008允许你构建针对多个.NET框架版本的应用。你可以从下面的博客贴子里进一步了解其中的工作原理:   VS 2008 Multi-Targeting Su ort   VS 2008 Web设计器和C 支持   VS 2008包含一个显著改进的HTML web设计器。该设计器提供了分割视图编辑,嵌套母板页,以及出色的C 集成。   A .NET还提供了一个新的控件,该控件对数据UI场景提供了非常灵活的支持,允许对输出的标识做完全的定制,与VS 2008中的新C 支持还有良好的协作。   A .NET AJAX和JavaScript支持   .NET 3.5 内置提供A .NET AJAX,还添加了支持We art的UpdatePanel,支持JSON的WCF,以及N个缺陷修补和性能改进等方面的新特性。VS 2008还对集成JavaScript和AJAX进你的应用提供了极棒的支持:   VS 2008 JavaScript Intellise e   VS 2008 JavaScript Debugging
语言改进和LINQ
  VS 2008中的新VB和C#编译器对这些语言做了显著的改进。两者都添加了函数式编程概念的支持,允许你编写更干净,更简洁,更具有表达性的代码。这些特性还促成了我们称之为LINQ(语言级集成查询)的新编程模型,使得查询和操作数据成为.NET中的一等编程概念。   下面是我撰写的一些讨论这些新语言特性的文章(用C#作为示例):   自动属性,对象初始化器,和集合初始化器   扩展方法   Lambda表达式   查询句法   匿名类型   LINQ to SQL中的数据访问改进   LINQ to SQL是.NET 3.5中内置的OR/M (对象关系映射器)。它允许你使用.NET 对象模型对关系数据库进行建模。然后你可以使用LINQ对数据库进行查询,以及更新、插入,删除数据。LINQ to SQL完整支持事务,视图和存储过程。它还提供了一个把业务逻辑和验证规则结合进你的数据模型的简易方式。下面是一些我讨论如何使用LINQ to SQL的文章:   Part 1: Introduction to LINQ to SQL   Part 2: Defining our Data Model Cla es   Part 3: Querying our Database   Part 4: Updating our Database   Part 5: Binding UI using the A :LinqDataSource Control   我会在以后的几周内再往这个系列里添加几篇文章。我认为你会发现LINQ to SQL显著地简化了构建非常干净的数据模型以及编写极其干净的数据代码。
其他改进
  上面的列表只是所做改进的一小部分。针对客户端开发,VS 2008 包含了WPF设计器和项目支持。ClickOnce 和WPF XBA 现在在FireFox中也工作了。WinForms和WPF项目现在也能使用A .NET 应用服务(成员,角色和用户数据)来漫游用户数据了。办公开发也更加丰富了,包括对Office 2007 Ri on的集成支持。WCF和Workflow项目和设计器也包括在VS 2008中了。单元测试的速度大为提高,而且单元测试的支持现在包括在VS Profe ional版本(而不仅仅是VSTS版了)中了。连续集成支持现在也内置于TFS中了。AJAX web测试(单元和压力)现在也由VS Test产品支持了。还有许许多多多的改进,这里无法一一提及了。
注意事项
  在安装VS 2008 和.NET 3.5 Beta2之后,还有2件重要的事情你应该马上做:   1) 你应该下载和运行这个批文件。这只要几秒钟就可以运行完,它修补了这个星期早些时候我们发现的System.Web.Exte io .dll版本政策的问题,该程序集包含了 A .NET AJAX。如果你不运行这个批文件,那么用A .NET AJAX 1.0 和 VS 2005构建的现有的A .NET 2.0项目就会自动地运载随 .NET 3.5 Beta2发布的新A .NET AJAX 版本。这会工作而且运行良好,但会不小心导致你的VS2005应用依赖于.NET 3.5。运行这个批文件会改变新的System.Web.Exte io .dll 程序集的版本绑定政策,确保你只在你明确构建.NET 3.5项目时才使用新的.NET 3.5 A .NET AJAX版本。   2) 假如你曾经在你的机器上安装过Orcas或VS 2008的早期版本(Beta1 或某个CTP 版本)的话,你需要在安装Beta2后重新设定你的VS 2008设置。如果你不这么做的话,有些设置会非常奇怪(一些窗口在出现在奇怪的地方),你也有可能看到一些IDE性能问题。你可以在命令行上对VS 2008的IDE版本键入“DevEnv /resetsettings”来重新设定你的配置:
加密处理
  信息安全是计算机应用的首要问题之一,但目前关于.NET加密功能的范例却少之又少。有鉴于此,本文探讨了在.NET平台下加密/解密文件的一般过程,并提供了一个加密/解密文件的工具。   Web服务以不容置疑的态势迅速发展,促使许多单位开始考虑.NET之类的开发平台。但是,出于对安全问题的担心,一些单位总是对采用新技术心存顾虑。好在有许多成熟的安全和网络技术,例如虚拟私有网络(VPN)和防火墙等,能够极大地提高Web服务应用的安全和性能,让开发者拥有选择安全技术的自由,而不是非得使用尚在发展之中的XML安全技术不可。   虽然安全是信息系统的首要问题,但有关.NET安全和加密工具的范例却少之又少。看看大多数.NET书籍的目录,找不到任何有关安全的题目,更不用说关于密码系统的探讨了。   有鉴于此,本文将介绍如何在VB开发中运用.NET的加密和密钥生成类,提供一个可用来加密和解密文件的工具Cryption。有了这个工具,你就可以在硬盘上保存各种机密文件,例如所有的密码/用户名字信息、收支文件、以及其他想要保密的信息,还可以加密那些通过Internet发送的文件。加密技术的用途非常广泛,你可以进一步定制本文提供的工具满足某些特殊需要,例如增加批处理能力等。
安全威胁
  攻击和泄密是计算机面临的两大安全威胁。攻击可能来自病毒,例如它会删除文件、降低机器运行速度或引发其它安全问题。相比之下,泄密往往要隐蔽得多,它侵害的是你的隐私:未经授权访问硬盘文件,截取通过Internet发送的邮件,等等。泄密还可能伴随着攻击,例如修改机密文件等。   针对泄密的最佳防范措施就是加密。有效的加密不仅杜绝了泄密,而且还防范了由泄密引发的攻击。加密技术有时还用于通信过程中的身份验证——如果某个用户知道密码,那么他应该就是那个拥有这一身份的人。   然而必须说明的是,没有一种防范泄密的安全技术是绝对坚固的,因为密码有可能被未经授权的人获得。
加密前提
  首先,要想使用.NET的安全功能,就必须用Imports语句引入加密用的包。试验本文涉及的任何代码之前,请在VB代码窗口的顶部加入下列Imports语句:   Imports System.IO   Imports System.Text   Imports System.Security.Cryptography   第二,美国政府过去限制某些加密技术出口。虽然这些限制不再有效,.NET框架在Windows的出口版本中禁用了“高级”加密技术。如果你的 Windows不带高级加密能力,可以从微软网站下载更新包:对于Windows 2000,安装Service Pack 2包含的High Encryption Pack;对于NT,安装Service Pack 6a。对于Windows ME、95、98的用户,IE 5.5也包含了High Encryption Pack。
工具概况
  本文提供的工具可用来加密和解密文件,如果你急着给一些文件加密,只需直接启动本文后面提供的工具即可。   这个工具提供了一个用来输入文件名字的文本框和一个输入密钥的文本框,通过便捷的用户界面提供加密、解密和密钥生成功能。在图一中,上方的文本框用来输入待加密/解密文件的名字;下面的文本框用来输入8个字符的密码。执行加密操作之后将生成一个新的文件,这个经过加密的文件和原始文件在同一目录下,文件名字也和原始文件的一样,但加上了“xx”后缀,例如,假设原始文件是MyFile.txt,则加密得到的文件是MyFilexx.txt。   加密好之后,原始文件不一定非删除不可,但一般来说最好删除,因为加密的根本目的就是为了隐藏原始文件的数据。如果要从加密后的文件恢复出原始文件,在上面的文本框中输入MyFilexx.txt,然后提供密码,Cryption工具将创建一个与原始文件一样的MyFile.txt文件。也就是说, Cryption把文件名字后面的“xx”看作是要求解密密文的标志。   注意:加密文件之后如果忘记了用来加密该文件的密码,再想恢复出原始文件就不可能了。当然,这与密码本身的复杂程度有关,要想保证文件的安全,最好采用较复杂的密码,例如混合运用字母、数字和特殊字符(如“$”符号等)。   .NET提供的加密技术不止一种,不过本文讨论的主要是对称加密。对称加密也称为私有密钥加密,它的特点是加密和解密用的是同一个密钥(实际上是同一种算法),解密方和加密方都有责任保障密码的安全(对于公用密钥、不对称加密,密钥一共有两个,其中一个密钥是公开的,这是当前公认最有效的加密技术,但就速度而言要比对称加密算法慢不少)。   在正式利用.NET加密类加密文件之前,首先必须从用户提供的密码生成一个密钥。密钥可以利用Hash函数生成,Hash函数把用户的密码字符串转换成一组类似随机数序列的、无意义的数据,这组数据可作为密钥使用,在加密过程中对原始数据进行唯一性变形处理。   例如,用密钥加密数据的一种办法是把原始数据的ASCII码加上密钥的ASCII码:   密钥:ab = ASCII: 97, 98   数据:merry = ASCII: 109, 101, 114, 114, 121   把这组数据的ASCII码加上密钥的ASCII码(必要时重复使用密钥),得到的加密结果是:   97 98 97 98 97   +109 +101 +114 +114 +121   206 199 211 212 218   对于同样的数据,Hash算法总是生成同样的结果(这就是说,对于同一个密码,同一Hash算法总是生成相同的bit序列)。实际上,在本文提供的代码中,利用.NET的SHA1CryptoServiceProvider类的ComputeHash方法可以验证这一点,例如,对于同一个输入参数 morph,任何时候该方法总是返回下面的结果:124,230,93,253,197,206,136,72。因此,如果有人知道密码以及生成密钥的算法,他也可以轻松地推算出密钥。
加密/解密
  .NET加密技术要求密钥有确定的长度,例如,DES(Data Encryption Standard)函数要求密钥的长度是64位,Rijndael则要求128、192或256位长度的密钥。密钥越长,加密强度越高。对于DES之外的加密算法,查询LegalKeySizes属性即可得到它允许的密钥长度,包括MinSize(支持的最小密钥长度)、MaxSize(最大密钥长度)、 SkipSize(增量)。SkipSize表示密钥最大长度和最小长度之间可用长度的间隔,例如,Rijndael算法的SkipSize值是64位。   利用下面的代码可以得到密钥的长度信息:   ' 创建DES加密对象   Dim des As New DESCryptoServiceProvider()   Dim fd() As KeySizes   fd = des.LegalKeySizes() 'tells us the size(s), in bits   MsgBox("加密类型=" & des.ToString() & Chr(13) & "minsize = " & fd(0).MinSize & Chr(13) & _   "maxsize = " & fd(0).MaxSize & Chr(13) & "skipsize = " & fd(0).SkipSize)   运行上面的代码,得到的结果是64、64、0。如果把加密对象的声明改成TripleDESCryptoServiceProvider(),得到的结果是128、192、64。   说明:DES算法要求输入一个8字节的密码,但实际使用的密钥只有56位(7个字节),每一个字节的最后一位不用(它作为校验位使用,但不用于实际的加密过程)。   下面的代码开始生成本文示例程序的密钥:   Public Class Form1   Inherits System.Windows.Forms.Form   ' 保存密钥的8字节的数组   Private TheKey(7) As Byte   ' 在向量中放入一些随机数据   Private Vector() As Byte = {&H12, &H44, &H16, &HEE, &H88, &H15, &HDD, &H41}   首先,代码定义了保存密钥和初始向量(请参见稍后的详细说明)的两个变量。向量的初值这里用随机数据填充,当然,通过密码和Hash算法也可以获得向量的初值。下面的过程从用户输入的密码创建出密钥:   Sub CreateKey(ByVal strKey As String)   ' 保存密钥的字节数组   Dim arrByte(7) As Byte   Dim AscEncod As New ASCIIEncoding()   Dim i As Integer = 0   AscEncod.GetBytes(strKey, i, strKey.Length, arrByte, i)   ' 获得密码的Hash值   Dim hashSha As New SHA1CryptoServiceProvider()   Dim arrHash() As Byte = hashSha.ComputeHash(arrByte)   ' 将Hash值保存到密钥   For i = 0 To 7   TheKey(i) = arrHash(i)   Next i   End Sub   用户的密码(strKey)传入到CreateKey过程,分解成一组ASCII值保存到一个字节数组。把这个字节数组传递给 SHA1CryptoServiceProvider类的ComputeHash方法,返回一个Hash值。把这个Hash值保存到TheKey数组,供以后的加密/解密过程使用(注意SHA1CryptoServiceProvider实际能够支持160位,但本文示例程序只用到64位)。   那么,初始向量究竟起什么作用呢?这个字节数组有8个元素,就象密钥一样,但向量和密钥的作用是不同的,向量用来避免DES之类的算法一个特有的问题。在DES之类的算法中,原始数据被分成8字节一块然后分别处理。DES在加密一块数据时,要用到前一块数据的模式,也就是说,如果改动了原始数据中第一块的某个字符,所有后继的块的内容都将随之改变,从而避免了一系列相连接的块中出现重复块的问题。   例如,假设你一时高兴,发了一个邮件,内容只有几个重复的单词“Melanie! Melanie! Melanie! Melanie!”,在密钥和块序列中前一块的共同作用下,加密之后的密文不会出现重复现象。然而,进一步考虑这个加密过程可以发现,如果用同一个密钥加密多个邮件,且邮件开头的问候语都相同,则邮件开头的一部分很容易受到攻击。由于这个原因,我们用初始向量来模拟前一个块。   本文加密/解密工具中的下面这段代码示范了如何加密文件:   Sub Encrypt(ByVal inName As String , ByVal outName As String )   Try   ' 创建缓冲区   Dim storage(4096) As Byte   ' 已经写入的字节数量   Dim totalBytesWritten As Long = 8   ' 每次写入的字节数量   Dim packageSize As Integer   ' 声明文件流   Dim fin As New FileStream(inName, FileMode.Open, FileAccess.Read)   Dim fout As New FileStream(outName, FileMode.OpenOrCreate, FileAccess.Write)   fout.SetLength(0)   ' 源文件的大小   Dim totalFileLength As Long = fin.Length   ' 创建加密对象   Dim des As New DESCryptoServiceProvider()   Dim crStream As New CryptoStream(fout, _   des.CreateEncryptor(TheKey, Vector), _   CryptoStreamMode.Write)   ' 输出加密后的文件   While totalBytesWritten < totalFileLength   packageSize = fin.Read(storage, 0, 4096)   crStream.Write(storage, 0, packageSize)   totalBytesWritten = Convert.ToInt32(totalBytesWritten + _   packageSize / des.BlockSize * des.BlockSize)   End While   crStream.Close()   Catch e As Exception   MsgBox(e.Message)   End Try   End Sub   注意这段代码创建了三个文件流:fin,表示明文形式的原始文件;fout,加密结果文件;crStream,加密流,用来把DES加密的结果转入输出文件fout。增加一个crStream流的好处是不必把结果保存到临时文件或缓冲区。   加密过程与解密过程的唯一重要区别是,执行解密时,我们将使用DESCryptoServiceProvider对象的另一个方法CreateDecryptor,除此之外,两者其余的处理步骤(包括参数,文件流,等等)基本相同。
防止破解
  黑客和密码专家破解加密文件的办法主要有两个,第一是搜索密文是否有重复现象,第二是用暴力破解法获得密钥。首先我们考虑一下初始向量如何防止重复现象,然后再探讨一下防止暴力破解的关键问题。   破解密文的第一种方式是搜索样本——特别是重复的样本。人们在写信的时候总是喜欢用同样的文字开头,例如“亲爱的XXX”、“Dear Sir”等,如果多个邮件的开头文字相同且通过同一密钥加密,则每个密文信件的开头也相同。假设Antonio写给Melanie的所有加密信件都有相同的问候语“@4^F (2$@Fx”,解密者就会首先检查开头的几个单词是不是“Dear Melanie”。解密机密文件的一个重要步骤就是猜测文件中应当会出现的几个单词,所以我们不应该给解密者提供这种方便。在本文的示例中,初始向量的内容被附加到文件的开头,从而防止了出现重复现象。只有信件的开头才容易受到此类攻击。   计算机的运算速度和精度要远远超过人,特别擅长处理一些重复的任务,例如尝试每一种可能的密钥组合最终破解密钥。DES加密算法本身是不安全的,这种加密算法早在70年代就已经公之于众。而且,破解者如果想要让搜索密钥的过程自动化,同样可以方便地运用.NET的DESCryptoServiceProvider类。   对于一个128位、结合运用密钥/初始向量的加密方案,计算机尝试每一种可能的密钥组合要花多少时间?专家们的看法并不一致,有人认为需要数月,也有人认为装有专用硬件的价值6位数的计算机每秒能够验证数十亿个密钥,破解DES密文只需数小时。如果你的机密值得花数月时间去破解,那么最好改用 TripleDES或其他加密算法。从TripleDES的名字也可以猜出,这种加密方式采用三重数据加密标准算法,所以密钥的长度是192位,而不是 64位的DES密钥。记住,在其他条件相同的情况下,密钥越长,安全程度越高。   结束语:现在你已经了解了. NET DES加密算法的使用过程,接下去可以研究.NET的其他安全功能,包括极具吸引力的公用密钥加密方案。虽然公用密钥加密方案执行起来速度慢一些,但加密效果一般要比TripleDES好。
.NET之未来发展
  预测未来,在技术世界是常有的事儿。从高级语言的发展历史来看,编程世界从来就没有停止过脚步,变革时时发生、创新处处存在。以技术人员的角度来观摩未来,带着C# 4.0的脚步来看展望, 除了在函数式编程、并行计算和动态特性上大展拳脚,Meta Programming的概念已然浮出水面,将编译器变成一个Service,你可以自由控制在编译器和运行期的逻辑,那是多么美好而向往的未来呀,所以,我们坚信 4.0之后还有广阔的天地随着语言的变迁变得更加开阔。   概括Anders大师在C#设计过程中的思想,C#是语言美学的集大成者。例如,当使用foreach进行循环遍历之后,当应用using语句代替try/finally实现强制资源管理,当应该attribute进行运行时反射,当以LINQ进行语言级别的信息查询,这些语言级别的支持为C#实现面向对象编程带来强大的功能动力和美学感受。
常见的域名后缀
  .net是国际最广泛流行的通用域名格式。.net一般用于从事Internet相关的网络服务的机构或公司,当然任何人都可注册。   类型:.net   规则:   1、只提供英文字母(a-z,不区分大小写)、数字(0-9)、以及"-"(英文中的连词号,即中横线),不能使用空格及特殊字符(如!、$、&、? 等)。   2、"-"不能用作开头和结尾   3、长度不能超过63个字符

posted @ 2011-10-31 10:09  唐江兰  阅读(475)  评论(0编辑  收藏  举报