第 1 章 你真的了解C#吗
在正式介绍C#的语法和特性之前,让我们首先来了解下它的发展历程。因为只有知道了C#的概貌和由来,积累了必要的背景知识,我们才能更好地掌握C#,进而使用C#来编程。
1.1 什么是C#
C#(发音为C Sharp)是由微软公司开发的一种面向对象且运行于.NET Framework之上的高级程序设计语言。它的基本语法与C和C++类似,但相比较而言,C#更加简单易学。如果你之前已经对上述的任何一种语言有所了解,就可以通过学习,在很短的时间里使用C#来编程。
C#还具有很多特性,例如封装方法签名的委托(类似于C++中的方法指针)、可为空的值类型、泛型方法和Lambda表达式等,这些特性都是其他语言所不具有的。C# 2.0支持泛型类型,从而避免了强制类型转换带来的性能损失;还提供了迭代器,因此可更简单地为集合类型实现自定义的迭代行为。在C# 3.0中,语言集成查询(LINQ)表达式使查询操作更为简单。C# 4.0中提供的动态类型,可以让开发者为类型实现自定义的动态行为,从而使在C#这样的静态语言中调用诸如Python的动态语言成为可能。
使用C#开发应用程序也比使用其他语言更简单、快速,因为C#语言是基于.NET Framework的。.NET Framework为开发应用程序提供了丰富的类库和图形控件,利用这些现有的控件就可以开发出一些应用程序。而且,C#的开发工具Visual Studio也提供了很多应用程序的模块,我们可以利用模块快速创建应用程序。
1.1.1 C#语言的发展历程
了解C#语言的发展历程具有重要的意义,因为只有当你知道了C#语言所具有的特性,才能更好地学习和掌握它们。
C#是微软公司在2000年6月发布的全新编程语言。在其诞生后的14年里,为了帮助开发人员更好地使用C#语言来编写应用程序,微软不断地更新C#语言的版本,每次升级都能带来让我们眼前一亮的新特性。表1-1列出了C#每个版本中所更新的特性和对应的.NET Framework版本。
表 1-1 C#各版本的新特性及对应的.NET Framework版本
C# 版本 | .NET Framework版本 | Visual Studio版本 | 发布日期 | 特性 |
---|---|---|---|---|
C# 1.0 | .NET Framework 1.0 | Visual Studio .NET 2002 | 2002.1 | 委托事件 |
C# 1.1 | .NET Framework 1.1 | Visual Studio .NET 2003 | 2003.4 | APM |
C# 2.0 | .NET Framework 2.0 | Visual Studio 2005(开始命名为Visual Studio) | 2005.11 | 泛型 |
C# 3.0 | .NET Framework 3.0 | Visual Studio 2008 | 2007.11 | 隐式类型的局部变量 |
C# 4.0 | .NET Framework 4.0 | Visual Studio 2010 | 2010.4 | 动态绑定 |
C# 5.0 | .NET Framework 4.5 | Visual Studio 2012 | 2012.8 | 异步和等待调用方信息 |
从表1-1可以看出,对于C#的每一个版本,微软都是围绕某个主题进行更新的,图1-1更形象地总结了每个C#版本的主题。
图 1-1
1.1.2 C#能编写哪些应用程序
对于读者来说,最想达到的效果莫过于学完C#之后能立刻去开发应用程序。可以这么说,只要掌握了C#,你就能编写所看到的任何应用程序了,比如音乐播放器、电子商务平台,以及一些服务程序等。下面就介绍几种常见的应用程序类型。
1. Windows桌面应用程序
用C#实现Windows桌面应用程序较其他语言来说更为简单快速。主要原因在于,Windows Forms模块提供了一个强大的控件库,其中包含按钮、菜单等常用控件,用户可使用这些控件,通过拖拉的方式轻松地建立Windows用户界面。
另一方面,C#开发环境Visual Studio也很好地集成了Windows Forms模块,方便我们创建这类应用程序;而在.NET 3.0之后(对应于Visual Studio 2008),我们还可以使用Windows Presentation Foundation(WPF)来实现Windows桌面应用程序,WPF提供了更大的灵活性和更漂亮的外观,如图1-2所示。
图 1-2
2. Web应用程序
Web应用程序就是一些Web页面,通过浏览器可以查看这些Web页面。.NET Framework提供了ASP.NET技术来帮助我们实现该类应用程序。ASP.NET模块中包含丰富的控件库,我们可以利用这个控件库来制作出漂亮的Web页面。此外,Visual Studio也集成了该类应用程序的模板(如图1-3所示),使用模板来建立Web应用程序速度更快。
图 1-3
3. Web服务
Web服务是实现分布式应用程序的一种方式。这里举一个生活中的例子,帮助大家理解什么是服务:我们去饭店吃饭,就会有服务员来为我们服务点单。可以发现,服务即指我们不想自己去做,而希望别人帮助我们完成某件事情。
在开发过程中,我们也需要实现那些为其他应用程序提供服务的程序,C#语言可以帮助我们实现这类应用程序。在.NET Framework 3.0之后,微软提供了Windows Communication Foundation(WCF)技术来实现Web服务,Visual Studio中也集成了该应用程序的模板(如图1-4所示)。
图 1-4
C#可以实现任何类型的应用程序,上面只是简单介绍了其中最常见的3类应用程序。对于上面介绍的3种具体的技术,本书不会多作介绍,请读者朋友们参考相关图书和资料进行学习。
1.2 什么是.NET Framework
在前面的介绍中,.NET Framework这个词已经出现过多次了,然而它到底是什么呢?
我们可以这样去理解.NET Framework(.NET框架):C#是一门编程语言,它用于实现与计算机的对话,但C#编写的程序是需要编译和运行的,.NET Framework就是应用程序运行时的执行环境,为应用程序的执行提供以下几种服务。
-
全面的类库 .NET Framework提供了丰富的类库以供调用,这使我们不必再去编写大量代码去处理常见的操作。
-
内存管理 在许多其他的编程语言中,开发人员需要负责内存的分配和释放,以及对象生命周期的处理等任务。.NET Framework为了减轻开发人员的工作,提供了内存管理服务。
-
通用类型系统(Common Type System,CTS) CTS定义了可以在中间语言中使用的预定义数据类型。
-
开发结构和技术 .NET Framework提供了开发特定应用程序所需的库,如Web应用程序的ASP.NET技术。
-
语言互操作性 面向.NET Framework的语言编译器都提供了生成中间语言代码的机制,这种机制使得不同语言之间进行互操作成为可能。
1.2.1 .NET Framework的组成
前面简单介绍了.NET Framework的概念,接下来,让我们看看.NET Framework具体是由哪几部分组成的。
.NET Framework包括公共语言运行时(Common Language Runtime,CLR)和.NET Framework类库(Framework Class Library,FCL)。
1. 公共语言运行时
公共语言运行时是.NET Framework的核心基础。我们可以将CLR看成一个在执行时管理代码的代理,它提供了内存管理、线程管理和异常处理等服务,而且还负责对代码实施严格的类型安全检查,保证了代码的正确性。我们将受CLR管理的代码称为托管代码(managed code),将不受CLR管理的代码称为非托管代码(unmanaged code)。
CLR包含两个组成部分:通用类型系统(Common Type System,CTS)和公共语言规范(Common Language Specification,CLS)。下面来具体了解这两个组件的功能。
-
CTS
C#和VB.NET都是由CLR进行管理的,但是它们的语法和数据类型各不相同,CLR是如何对这两种不同的语言进行托管的呢?
这得益于CTS。CTS用于解决不同语言之间数据类型不同的问题,如C#中整型是
int
,而VB.NET中的整型却是Integer
,通过CTS可以把这两个类型变成通用类型Int32
。所有.NET语言都共享CTS这一类型系统,从而使它们之间能够实现无缝互操作。CTS类型主要分为两大类:引用类型和值类型。如图1-5所示,这两种类型之间存在着相互转化,转化方法分别为装箱(box)和拆箱(unbox)。更多有关两类CTS类型转换的内容将在第10章中介绍。
图 1-5
-
CLS
.NET下的语言不仅仅存在数据类型的不同,语言规范上也有显著的区别,公共语言规范(CLS)就是为了解决这个问题而诞生的。
CLS是一种最低的语言标准,它制定了以.NET平台为目标的语言所必须支持的最小特征,以及某一语言与其他.NET语言之间实现互操作所需要的完备特征。凡是遵守这个标准的语言,在.NET框架下都可以实现互相调用;不符合公共语言规范的代码就不能被其他语言调用,继而不能与其他语言进行互操作。
比如在C#中,变量命名是区分大小写的,而VB.NET却不区分大小写,这样CLS就规定,编译后的IL代码除了大小写之外必须还有其他的不同。图1-6很好地演示了两者之间的区别。
图 1-6
2. .NET Framework
.NET Framework类库就是一组DLL程序集的集合,其中包含了大量定义好的类型,这些类型都公开了一些功能。我们可以使用这些公开的功能开发出多种应用程序,例如前面介绍的Windows Forms和ASP.NET应用程序。
由于FCL中包含了数量极多的类型,因此有必要将相关的一组类型放到一个单独的命名空间中加以区分,例如System.IO命名空间中就包含了用于执行I/O操作的类型。因此,在使用FCL中某个类时,还必须知道该类所在的命名空间。
图1-7可以帮助大家更好地理解公共语言运行时、类库与应用程序之间以及与整个操作系统之间的关系。
图 1-7
1.2.2 C#与.NET Framework的关系
C#是面向.NET Framework的语言,除了C#之外,VB.NET和F#也都是面向.NET Framework的语言。.NET Framework为这些语言提供了执行环境,这些语言则可以调用.NET Framework所提供的类库来开发各种应用程序。大家可以通过图1-8更好地理解两者之间的关系。
图 1-8
1.2.3 C#代码的执行过程
在Visual Studio开发工具下,我们只需要按F5就可以编译和执行C#代码了,但是C#代码到底是如何执行的呢?为了使C#代码能够运行,必须将其转换为目标操作系统能够理解的语言,即本机代码(native code)。在.NET Framework平台下,该过程包括两个阶段。
-
C#代码编译为中间语言代码的阶段——在编译C#代码时,并不是立即创建专用于操作系统的本机代码,而是由C#编译器(Visual Studio中集成了C#编译器)把代码编译为通用中间语言(Common Intermediate Language,CIL)代码。
-
中间语言代码编译为本机代码的阶段——要使C#代码能够运行,还需进一步将CIL代码转换为特定CPU的本机代码,该过程由即时编译器(Just-In-Time,JIT)来完成。
下面详细介绍C#代码的编译和执行过程。
1. C#代码编译为中间语言代码阶段
并不是只有C#代码才能被编译为中间语言代码,其他面向.NET的语言(如VB .NET)在执行之前也都需要先编译为中间语言代码。该过程由对应的编译器去完成,具体过程如图1-9所示。
最终创建的IL代码将存储在一个程序集中,程序集中除IL代码外,还将包括元数据和可选的资源文件。元数据用来描述代码中的类型,这种描述针对3个方面:类型定义的描述、类型成员的描述和类型引用成员的描述。可选的资源文件指IL代码中使用的其他数据,如图片文件等。
图 1-9
程序集分为两种:扩展名为.exe的可执行文件,以及扩展名为.dll的可供其他程序调用的库文件。
2. 中间语言代码编译为本机代码阶段
为了使IL代码能够运行,必须把它编译为本机代码,即CPU指令。这个过程由CLR的JIT编译器来完成。其编译过程如图1-10所示。
图 1-10
3. 执行本机代码
JIT编译生成本机代码之后,编译好的本机代码会被放置到一个缓冲区中缓存,下次再调用相同的代码时,可直接运行缓冲区中现有的本机代码,从而避免重新验证IL代码以及把它编译为本机代码的过程。使用这种方法,系统只在首次调用时才会造成一些性能损失(即发生JIT过程)。
1.3 归纳总结
本章简单介绍了C#语言的特点和发展历程,阐释了.NET Framework与C#之间的关系,并给出了C#代码的执行过程。相信通过本章的学习,你已经对C#有了一个全面的认识。下一章将带领大家创建一个简单的控制台程序。