C#程序设计简介本章介绍C#语言的特点、开发C#程序的基本步骤、C#程序的构成、基本输入输出以及C#的开发工具等.
通过本章的学习,可以对C#程序设计有一个初步的认识.
1.
1C#语言及其环境C#(发音为"CSharp")是由Microsoft开发的面向对象的编程语言.
它继承了C和C++、Java等语言的优点并且有了较大的发展,是迄今为止最为优秀、最为通用的程序设计语言之一.
1.
1.
1C#的产生与发展C#是直接从世界上最成功的计算机语言C和C++继承而来,又与Java紧密相关.
理解C#的产生与发展有助于C#的学习.
1.
结构化编程与C语言C语言的产生标志着现代编程时代的开始.
C语言是20世纪70年代由DennisRitchie在基于UNIX操作系统上创建的.
在一定意义上,20世纪60年代的结构化编程造就了C语言.
在结构化编程语言产生之前,大型的程序是很难编写的.
因为往往在编写大型程序的时候,会由于存在大量的跳转、调用和返回很难进行跟踪调试.
结构化的编程语言加入了优化定义的控制语句,子程序中采用了局部变量和其他的改进,使得这种问题得到了解决.
C语言是结构化编程语言中最为成功的一种,至今C语言仍用常用的语言之一.
2.
面向对象编程与C++语言C语言还是有它自身的局限性.
到了20世纪70年代末期,很多项目的代码长度都接近或者到达了结构化编程方法和C语言能够处理的极限.
为了解决这个问题,出现了新的编程方法,即面向对象编程(简称OOP),程序员使用OOP可以编写出更大型的程序.
1979年初,BjarneStroustrup在贝尔实验室创造了C++.
C++是C的面向对象的版本.
对于C程序员,可以方便地过渡到C++,从而进行面向对象的编程.
20世纪90年代中期,C++成为广泛使用的编程语言.
3.
网络的发展与Java语言随着网络的发展,编程语言进入到的下一个主流就是Java.
Java的创造工作由1991年在Sun公司开始,其主要发明者是JamesGosling.
Java是一种面向对象的语言,它的语法和思想起源于C++.
Java最重要的一方面是具有编写跨平台、可移植代码的能力,Java能够将一个程序的源代码转换到被称为字节码的中间语言,实现了程序的可移植性.
该字节码在Java虚拟机上被执行.
因此,Java程序可移植到有Java虚拟机的任何环境中.
由于Java虚拟机相对比较容易实现,所以适用于大部分的环境.
在Java中采用中间语言是很重要的,在其后的C#中采用了类似的方案.
4.
C#语言的产生Microsoft公司在20世纪90年代末开发了C#,其首席设计师是AndersHeilsberg.
图11展示了C#的家族史.
C#的祖父是C,C#继承了C的语法、关键词和运算符.
C#建立在C++定义的对象模型基础上,并加以改进.
图11C#的产生历史C#起源于C和C++,并且与Java有许多相似之处,同时C#包含了许多创新的特性,这些特性将会在本书中进行详细的讲解.
5.
C#语言的发展C#语言从2002年正式发布以来,经历了多个版本,主要的版本如表11所示.
C#的发展是与C#的运行环境(Microsoft.
NET)以及集成开发工具(VisualStudio)同步发展的.
表11C#语言的各个版本年月C#版本.
NET版本VisualStudio版本2002-11.
01.
0.
3705.
0VisualStudio.
NET20022003-41.
1,1.
21.
1.
4322.
573VisualStudio.
NET20032005-112.
02.
0.
50727.
42VisualStudio20052006-113.
03.
0.
4506.
30VisualStudio20052007-113.
03.
5.
21022.
8VisualStudio20082010-44.
04.
0.
330319VisualStudio20102012-95.
04.
5VisualStudio20122013-115.
04.
5.
1VisualStudio20132014-116.
04.
6VisualStudio20152017-37.
04.
7VisualStudio2017C#语言仍在迅速发展之中,除了主要用在Windows平台,现在还可以用于Linux、MacOS平台.
对于学习者而言,C#可以很快被C和C++、Java程序员所熟悉,而且C#避免了其他语言中一些容易出错、难于使用的成份,并且利用集成开发环境VisualStudio可以大大提高程序开发的效率.
可见,学习C#语言不仅必要,而且是可以学得好的.
1.
1.
2C#的环境——Microsoft.
NET尽管C#是一种可以单独学习的计算机编程语言,但是它与其运行期环境——Microsoft.
NET框架仍然有密切联系.
究其原因有二:其一,微软最初设计C#语言是为了编写.
NET框架;其二,C#使用的函数库是.
NET框架定义的函数库中的一部分.
因此,虽然可以把C#与.
NET环境分开,但是它们实际上是密切联系的.
由于以上原因,对.
NET框架有一个基本了解是非常必要的.
事实上,本书不仅介绍C#语言本身,还介绍C#语言在.
NET环境中的应用.
1.
什么是Microsoft.
NETMicrosoft.
NET是一个综合性的术语,它描述了微软公司最近才发布的许多技术.
总的说来,Microsoft.
NET包括以下技术领域:.
NET框架(.
NETFramework).
NET语言,包括C#,F#,C++,VisualBasic等开发工具,主要是VisualStudio开发工具VisualStduio操作系统(Windows及其他)WebFormADO.
NET.
XMLWinFormmWPFLINQWFWCFC#F#C++VB公共语言规范(CLS)公共语言运行环境(CLR).
NETframework基础类库(BCL)应用程序这几个部分之间的关系,如图12所示.
图12Microsoft.
NET体系其中.
NET框架位于操作系统之上,它定义了一种支持开发和执行应用程序的环境.
.
NET框架定义了包含了两个重要的部分.
一个是公共语言运行环境(CommonLanguageRuntime,CLR),它管理程序的执行.
另一个是.
NET类库,使得我们在进行C#编程时可以调用这些库.
2.
公共语言运行环境公共语言运行环境(CLR)管理.
NET代码的执行,可以认为它是一个执行C#程序的虚拟运行环境(虚拟机).
CLR负责为应用程序提供内存分配、线程管理、安全以及垃圾回收等服务,负责对了代码进行严格的类型安全检查,以保证代码安全、正确地运行.
C#源程序首先编译成中间代码,在执行时,再即时转换成机器指令.
如图1-2所示.
JIT编译在内存中机器指令可执行程序(.
exe)含有MSIL及元数据C#源程序(.
cs文件)图13C#程序的编译与执行过程当编译C#程序时,编译器并不输出CPU指令,而是一种特殊的中间代码.
这些中间代码被称为通用中间语言(CommonIntermediateLanguage,简称CIL)(又称为MicrosoftIntermediateLanguage,简称MSIL或IL).
CIL定义了一系列与CPU类型无关的可移植指令集,可以认为是一种可移植的汇编语言.
当程序运行时,CLR负责把中间代码转换成可执行代码.
从这个角度说,任何被编译成MSIL的程序都能运行在实现了CLR的环境下.
这就是为什么.
NET框架具有可移植性的原因.
这个转换过程一般是使用JIT编译器,JIT代表"JustInTime",意思是"即时地".
当.
NET程序运行时,CLR激活JIT编译器,JIT编译器把MSIL转换成机器指令(本地代码).
除了CIL指令,当编译C#程序时输出的另一部分是元数据(Metadata).
元数据用来描述在程序本身的信息,特别是程序的类型信息,它与IL保存于同一个文件中.
在CLR定位与装载类型时,系统通过读取并解析元数据来获得应用程序中的类型信息,由于整个过程中CLR始终根据元数据建立并管理对应特定应用程序的类型,从而保证了类型安全性.
—般来说,当编写一个C#程序时,创建的程序被称为托管代码(managedcode)或受控代码.
由于托管代码是在CLR的控制下执行,因此受到一些限制,当然也获得一些好处.
受到的限制有:编译器必须产生面向CLR的CIL文件,必须使用.
NET框架库函数(如同C#那样).
受控代码的好处有:混合语言编程的能力、更好的安全性、支持版本控制等等.
与托管代码相对应的是非托管代码(unmanagedcode),非托管代码的执行不受CLR的控制.
在.
NET框架以前的所有Windows程序都是非托管控代码.
因为托管代码和非托管代码是可以共同运行的,所以事实上C#程序可以与以前的程序并存(在本书的最后一章介绍了这样的例子).
总之,CLR管理受控代码的执行,它分两步来进行,并且保证程序的安全性.
3.
.
NET类库.
NET框架的另一个重要部分是.
NET类库.
这些类库提供了包括基础类库、输入输出、图形用户界面、网络功能、数据库访问等多方面的功能.
C#编程时可以使用这些库.
其中基础类库又称为BCL(basicclasslibrary),它封装了大量的基础功能,如文件操作、图形操作、网络连接、XML文档、安全加密等.
我们在编程时可以调用这些功能,而不用所有的程序都从最底层开始编写.
本书中会对这些功能进行介绍.
在BCL之上,又有大量的类库,具有更复杂的功能.
如WindowsForm表示Windows窗体,WebForm表示网页表单,ADO.
NET表示数据库访问功能,在新版本的.
NETFramework更增加了诸如:WPF(WindowsPresentationFoundation)是基于Windows的用户界面框架;WCF(WindowsCommunicationFoundation)是通讯方面的类库;WF(WorkflowFundation)是工作流框架,Linq是基于语言的查询等等.
这使得应用程序编写起来更方便.
4.
公共语言规范及.
NET语言.
NET可以使用C#语言来编程,也可以使用F#、C++、VisualBasic等多种语言来进行编程,它们都可以编写托管代码,并生成CIL中间指令,所有各种语言编写的程序可以互相调用,也就是说.
NET能进行跨语言集成.
如果要托管代码能将被用其他语言所编写的程序使用,它必须遵守公共语言规范(CommonLanguageSpecification,CLS).
CLS描述了不同的编程语言都应具有的特征集,比如程序中使用一些通用的数据类型,而不使用一些特定的数据类型.
当编写要被其他语言调用的程序组件时,遵循CLS显得尤其重要.
5.
开发工具VisualStudio是.
NET的集成开发工具,它具有编辑、编译、调试程序与项目管理的功能.
还有一些相关的工具,如反汇编、证书管理、注册工具、XML工具等等.
正是由于有了它们的支持,.
NET才变得如此强大.
在我们的学习过程中,可以使用一些命令行的工具,但主要还是使用VisualStudio,它功能强大,而且使用方便.
微软提供了免费的及专业的VisualStudio版本,可以在http://www.
visualstudio.
com网站上下载.
6.
关于跨平台的框架早期.
NET框架主要用于Windows平台,但是现在.
NET并不局限于Windows平台,借助于Mono或.
NETcore,C#也可以用于Linux及MacOSX平台.
其中mono是第三方提供的框架,而.
NETcore则是微软提供的开源、免费的框架.
.
NETCore是.
NETFramework的新一代版本,它具有跨平台(Windows、MacOSX、Linux)能力.
与.
NETFramework相似,它提供了编译、运行的环境(如CoreCLR),也提供了基本的类库(如CoreFX),微软还提供了开发工具(如VisualStudioCode).
由于.
NETcore的基本类库与.
NETFramework的基本类库具有高类的相似性,可以开发人员很容易在两种框架间相互转换,从而开发出跨平台的应用程序.
值得一提的是,微软还提供了Xamarin等开发工具,可以使用C#开发来开发移动应用程序,包括iOS、Android、WindowsPhone和MacApp.
简单地说,.
NETcore是.
NETFramework跨平台的版本,Xamarin是手机开发用的环境,它们与.
NETFramework的运行环境不同,但所用的语言、所用的库则有很多相似性,本书以.
NETFramework为主进行讲解.
1.
1.
3C#的特点C#代表着编程语言演变的一个新阶段,它继承了C++和Java这两种世界上最重要的语言的优点,并且还增加了委托、事件、索引器、Lambda表达式、并行编程等创新性特点;同时,C#语言利用了.
NET作为其强大的平台,使得它在Windows图形用户界面、ASP.
NETWeb应用及ADO.
NET数据库等方面有广泛的应用.
下面从学习和使用的角度来介绍C#的特点.
当读者学完本书后会对C#语言的这些特点有更深的理解.
1.
简单易学衍生自C++的C#语言,除去了C++中不容易理解和掌握的部分,如最典型的指针操作、ALT、#define宏等,降低了学习的难度;同时C#还有一个特点就是它的基本语法部分与C++、Java语言几乎一模一样.
这样,无论是学过C#再学C++、Java,还是已经掌握了C++、Java语言再来学C#,都会感到易于入门.
2.
面向对象C#是面向对象的编程语言.
面向对象技术较好地适应了当今软件开发过程中新出现的问题,包括软件开发的规模扩大、升级加快、维护量增大以及开发分工日趋细化、专业化和标准化等,是一种迅速成熟、推广的软件开发方法.
面向对象技术的核心是以更接近于人类思维的方式建立计算机逻辑模型,它利用类和对象的机制将数据与其上的操作封装在一起,并通过统一的接口与外界交互,使反映现实世界实体的各个类在程序中能够独立、自治、继承;这种方法非常有利于提高程序的可维护性和可重用性,大大提高了开发效率和程序的可管理性,使得面向过程语言难于操纵的大规模软件可以很方便的创建、使用和维护.
C#具有面向对象的语言所应有的一切特性如封装、继承与多态.
在C#的类型系统中每种类型都可以看作一个对象,甚至对基本类型,C#提供了一个叫做装箱(boxing)机制,使其成为对象.
3.
安全稳定对网络上应用程序的另一个需求是较高的安全可靠性.
用户通过网络获取并在本地运行的应用程序必须是可信赖的,不会充当病毒或其他恶意操作的传播者而攻击用户本地的资源;同时它还应该是稳定的,轻易不会产生死机等错误,使得用户乐于使用.
C#特有的机制是其安全性的保障,同时它去除了C++中易造成错误的指针,增加了自动内存管理等措施,保证了C#程序运行的可靠性.
内存管理中的垃圾收集机制减轻了开发人员对内存管理的负担,.
NET平台提供的垃圾收集器(GarbageCollection,GC)将负责资源的释放与对象撤销时的内存清理工作.
同时,变量的初始化、类型检查、边界检查、溢出检查等功能也充分保证了C#程序的安全稳定.
4.
支持多线程多线程是当今软件技术的又一重要成果,已成功应用在操作系统、应用开发等多个领域.
多线程技术允许同一个程序有多个执行线索,即同时做多件事情,满足了一些复杂软件的需求.
C#中定义了一些用于建立、管理多线程的类和方法,使得开发具有多线程功能的程序变得简单、容易和有效.
在C#新版本中还支持异步编程、并行编程等高级特性.
5.
C#丰富的类库使得C#可以广泛地应用C#提供了大量的类,以满足网络化、多线程、面向对象系统的需要.
(1)语言包提供的支持包括字符串处理、多线程处理、异常处理、数学函数处理等,可以用它简单地实现C#程序的运行平台.
(2)实用程序包提供的支持包括哈希表、堆栈、可变数组、时间和日期等.
(3)输入输出包用统一的"流"模型来实现所有格式的I/O,包括文件系统、网络、输入/出设备等.
(4)图形用户界面的功能强大,不仅能实现Windows窗口应用程序,而且可以实现Web窗体应用.
(5)能用相应的类来实现从低级网络操作到高层网络应用.
C#的上述种种特性不但能适应网络应用开发的需求,而且还体现了当今软件开发方法的若干新成果和新趋势.
在以后的章节里,将结合对C#语言的讲解,分别介绍这些软件开发方法.
6.
灵活性和兼容性在简化C++语法的同时,C#并没有失去灵活性.
正是由于其灵活性,C#允许与C风格的需要传递指针型参数的API进行交互操作,DLL的任何入口点都可以在程序中进行访问.
C#遵守.
NET公用语言规范CommonLanguageSpecification(CLS)从而保证了C#组件与其它语言(如VisualBasic,VisualC++,JScript,J#等)的组件间的互操作性.
1.
1.
4C#和C、C++的比较对于变量声明、参数传递、操作符、流控制等,C#使用了和C、C++相同的传统,使得熟悉C、C++的程序员能很方便地进行编程.
同时,C#为了实现其简单、健壮、安全等特性,也摒弃了C和C++中许多不合理的内容.
下面选择几点,对于学过C语言或C++语言的读者而言,起一个快速参考的作用.
对于未学过C语言的读者,可以略过此节.
(1)全局变量C#程序中,不能在所有类之外定义全局变量,只能通过在一个类中定义公用、静态的变量来实现一个全局变量.
C#对全局变量进行了更好的封装.
而在C和C++中,依赖于不加封装的全局变量常常造成系统的崩溃.
(2)gotoC#支持有限制的goto语句,并通过例外处理语句try、catch、finally等来处理遇到错误时跳转的情况,使程序更可读且更结构化.
在一些细节上,也做了较好的处理,如switch语句中的case不会任意地贯通.
(3)指针指针是C、C++中最灵活,也是最容易产生错误的数据类型.
由指针所进行的内存地址操作常会造成不可预知的错误,同时通过指针对某个内存地址进行显式类型转换后,可以访问一个C++中的私有成员,从而破坏安全性,造成系统的崩溃.
而C#对指针进行完全的控制,程序只能有限制地使用指针操作.
同时,数组作为类在C#中实现,很好地解决了诸如数组访问越界等在C、C++中不作检查的错误.
(4)内存管理在C中,程序员通过库函数malloc()和free()来分配和释放内存,C++中则通过运算符new和delete来分配和释放内存.
再次释放已释放的内存块或未被分配的内存块,会造成系统的崩溃;同样,忘记释放不再使用的内存块也会逐渐耗尽系统资源.
而在C#中,所有的数据结构都是对象,通过运算符new为它们分配内存堆.
通过new得到对象的处理权,而实际分配给对象的内存可能随程序运行而改变,C#对此自动地进行管理并且进行垃圾收集,有效地防止了由于程序员的误操作而导致的错误,并且更好地利用了系统资源.
(5)数据类型的支持在C、C++中,对于不同的平台,编译器对于简单数据类型如int、float等分别分配不同长度的字节数,例如:int在IBMPC中为16位,在VAX-11中为32位,这导致了代码的不可移植性,但在C#中,对于这些数据类型总是分配固定长度的位数,如对int型,它总占32位,这就保证了C#的平台无关性.
(6)类型转换在C、C++中,可以通过指针进行任意的类型转换,常常带来不安全性,而C#中,运行时系统在处理对象时要进行类型相容性检查,以防止不安全的转换.
(7)头文件C、C++中用头文件来声明类的原型以及全局变量、库函数等,在大的系统中,维护这些头文件是很困难的.
而C#不支持头文件,类成员的类型和访问权限都封装在一个类中,运行时系统对访问进行控制,防止对私有成员的操作.
(8)结构和联合C、C++中的结构和联合中所有成员均为公有,这就带来了安全性问题.
C#中不包含联合,而且对结构进行了更好的封装.
1.
1.
5C#与Java的比较C#与Java在很多方面具有相似性,同时也有一些重要的差别.
C#和Java的相似之处主要包括:(1)二者都编译成跨平台的、跨语言的代码,并且代码只能在一个受控制的环境中运行.
(2)自动回收垃圾内存,并且消除了指针(在C#中可以使用指针,不过必须注明unsafe关键字).
(3)都不需要头文件,所有的代码都被限制在某个范围内,并且因为没有头文件,所以消除了类定义的循环依赖.
(4)都是严格的面向对象的语言.
(5)都具有接口(interface)的概念.
(6)都支持异常处理.
(7)都支持多线程.
(8)都支持元数据,不过,在C#中叫attribute,在Java中叫annotation.
(9)都支持Lambda表达式.
(10)都支持泛型.
C#在另外一些方面又与Java不同:(1)C#中的所有数据类型都是object的子类型,而Java中的数据类型分成基本数据类型及引用数据类型,只有引用类型是Object的子类型.
(2)C#中的数据类型中,增加了struct结构类型,而Java中没有结构类型.
(3)C#中的属性(property)的概念与字段(field)概念相分离,而Java中属性和域是用同一概念.
(4)C#中的委托、事件机制能更好地处理函数指针及回调函数,而Java中只有依靠接口等方法来实现.
(5)C#中的数组类型使用起来也更方便.
C#中还增加了索引器(indexer)的概念.
(6)C#中没有Java中的内部类和匿名类的概念,只有嵌套类的概念.
(7)C#中可以有限制地保留指针及goto语句.
(8)C#中可以有异步编程.
(9)C#更多的地支持动态语言特点.
(10)C#中有更多的语法糖,即可以更方便地书写一些特定的语句.
除以上一些方面的不同之外,C#中的一些细节在实现上与Java有一定的差别,比如,有关继承、访问控制、对象初始化的过程等等,这些方面的差别对于已学过Java的读者,要引起注意.
虽然在大部分编程的任务中不会触及到这些差别,但对于一些特定的情形,可能会引起意想不到的错误.
本书在讲解相关的细节时,会考虑到这些读者的需要,进行一些必要的介绍.
1.
2简单的C#程序在讨论更多的细节之前,先看几个简单的C#程序,目的是对C#程序有一个初步的认识.
C#程序有很多种类型,最常用的是控制台应用程序和Windows窗体应用程序.
前者是文本界面方式,后者是窗口图形界面方式.
1.
2.
1HelloWorld学习一门语言,一般从简单的"HelloWorld"开始,下面是一个简单的C#程序.
例11HelloWorld.
cs一个简单程序.
/*简单的C#示例程序.
为HelloWorld.
cs.
*/1usingSystem;2classHelloWorld{3//C#调用Main()作为程序的开始.
4publicstaticvoidMain(){5Console.
WriteLine("HelloWorld.
");6}7}本程序的作用是输出下面一行信息:HelloWorld!
整个程序是保存在一个名为HelloWorld.
cs的文件中的.
一般说来,C#的源程序文件名都是以.
cs作为扩展名的.
文件名本身没有强制性的规定,但最好能表示程序的作用,或者与其中的主要类的名字保持一致.
注意,为了讲解的需要,本书中的每行程序前面加的数字是行号,在实际书写程序时是不用输入行号的.
另外,例子前面的文件名.
cs表示本书配套电子资源源代码的文件名,如果名字后面没有加.
cs则表示是一个文件夹名或项目名.
程序中,由/*及*/所包含的一段是程序的注释.
另外,由//直到行尾的部分也是注释.
下面针对该程序的几个方面进行讲解.
1.
名字空间usingSystem表示导入名字空间(namespace).
高级语言总是依赖于许多系统预定义的元素,在C#中使用usingSystem表示导入系统已定义好的名字空间,这方便以后的使用.
下文要用到的Console的全称是System.
Console;当程序的前面使用了usingSystem后,使用System.
Console的地方就可以简写为Console.
在一定意义上,using大致相当于C/C++中的#include或者java语言中的import.
2.
类和类的方法C#是面向对象的语言,在进行编程的主要任务就是要定义类及类的方法.
程序中,用关键字class来声明一个新的类,其类名为HelloWorld.
整个类定义由大括号{}括起来.
在类的定义中,一个主要任务是定义方法.
方法相当于函数,但它必须位于类的定义之中.
在该类中定义了一个Main()方法,其中public表示访问权限,指明所有的类都可以使用这一方法;static指明该方法是一个静态方法,这种方法不用创建对象实例即可调用;void则指明Main()方法不返回任何值.
3.
程序的入口一个应用程序都有一个程序入口,程序的执行就从这里开始.
在C#中是用Main()方法为表示程序入口的.
值得注意的是,作为程序入口的Main()方法必须是static方法.
Main方法可以不为public,可以不带参数,返回值可以为void或int,所以Main()方法有多种形式.
另外,要注意Main的首字母大写.
Main()方法定义中,可以在括号()中的加入string[]args,表示是传递给Main()方法的参数,参数名为args.
Main()方法的参数实际就是命令行参数.
publicstaticvoidMain(string[]args)在C#中这个参数也可以没有,正如前面的程序中所示.
4.
程序的输入和输出在Main()方法的实现(大括号{}中),只有一条语句:Console.
WriteLine("HelloWorld!
");它用来实现字符串的输出,这条语句实现与C语言中的printf语句和C++中cout11///Form1的摘要说明.
12///13publicclassForm1:Form14{15publicForm1()16{17InitializeComponent();18}19privatevoidbutton1_Click(objectsender,System.
EventArgse)20{21Randomrnd=newRandom();22this.
textBox1.
Text=rnd.
Next().
ToString();23}24}25}5.
关于自动生成的代码从上面的过程可以看出,集成开发环境帮我们做了很多事情,其中界面设计的过程会自动生成代码,为了查看这个代码,需要使用"解决方案管理器"顶部的"显示所有文件"工具按钮,如图114所示.
图114"显示所有文件"工具按钮在"解决方案管理器"中,展开Form1.
cs就能看到Form1.
Designer.
cs,双击这个文件就可以看见设计器自动生成的代码,这个代码最好不要手工编辑,以免出错.
其中可以看到:有一个默认的名字空间以及对WinForms所要求的不同名字空间的引用(using);Form1类是从系统的Form中派生出来的;InitializeComponent方法负责初始化(创建)窗体及其控件(当在窗体中拖放下一些控件时,可以看到它的更多细节);Dispose方法负责清除所有不再使用的资源.
1.
2.
3对象的三个基本要素C#的程序都是面向对象的,对象是其中的核心概念.
对象是现实世界的物体的抽象.
在C#中的对象包括界面对象,如窗体、按钮、标签,也包括一些非界面的对象,如字符串、集合、书、人等等.
在C#程序设计就是要设计这些对象.
C#对象可以很复杂,可以有很多要素,但是一般地说,C#对象有三个基本的要素:属性、方法和事件.
1.
属性(property)属性的概念是用于表示对象的状态的,一般使用名词或形容词表示.
在C#中对象与属性之间用一个小数点".
"连接.
例如:button1.
Width表示按钮宽度,button1.
Height表示按钮的高度,label1.
ForeColor表示标签的前景色等等.
可以认为属性相当于对象中的一个变量.
在VisualStudio中,界面对象上右击,选"属性"可以打开属性窗口,或者直接按F4也可以打开属性窗口,如图122所示.
一个对象常常有多个属性,其中表示列出属性,表示按字母顺序排列,表示按分类顺序排列.
如果知道属性名,则按字母顺序排列更容易查找一些.
图115属性窗口有两种方式使用属性,一是给属性赋值(称为set),如button1.
Width=100表示使得其宽度为100;另一种方式是取得属性当前的值(称为get),如a=button1.
Width表示取得其宽度值并记录到变量a中.
2.
方法(method)方法是用于表示对象的功能、动作的,一般使用动词.
在C#中对象与方法之间也是用一个小数点".
"连接.
例如:this.
Show()表示显示当前窗体对象,Console.
WriteLine("hello!
");表示显示一行文本.
可以认为方法相当于对象中的函数,所以在使用时,需要带上圆括号,有时还需要带上参数.
例如自动生成的代码中components.
Dispose()、this.
ResumeLayout(false)等都是调用方法.
3.
事件(event)事件是用于表示对象的状态改变,是一种通知或消息机制,一般使用动词原形或分词形式.
在C#中对象与事件之间也是用一个小数点".
"连接.
例如:button1.
Click表示按钮被点击,this.
MouseMove表示当前窗体上鼠标移动事件发生,this.
Load表示窗体载入到内存的事件发生.
在VisualStudio中,界面对象上双击,可以打开该对象的默认事件(最常用事件),并对该事件进行编程.
对于更多的事件,则在界面对象上右击,或者按F4也可以打开属性窗口.
点击其中有一个闪电状图标可以列出该对象的所有事件,如图116所示.
双击其中的事件,则可以打开代码窗口进行代码的编写.
图116属性窗口中的事件事件在本质上是一种状态变化后对外界的消息通知,针对这个事件进行编程实际上就是处理这个消息.
为了处理某个消息,需要先注册这个消息,以便让事件发生后通知调用者.
VisualStudio中双击相应事件时,系统会自动生成这个事件注册的代码,这些代码在一个.
Designer.
cs中可以看到.
使用"视图|解决方案管理器(Ctrl+Alt+L)"打开解决方案管理器(该管理器默认是打开的),展开Form1.
cs,可以看见有个Form1.
Designer.
cs文件,如图122所示.
图16解决方案管理器中展开窗体文件双击Form1.
Designer.
cs可以看到Windows窗体设计器生成了这样的代码:this.
button1.
Click+=newSystem.
EventHandler(this.
button1_Click);如果我们手写编写,也可以这样写:对象.
事件+=函数名它表示对象的事件注册了一个函数,也就是说事件发生后,会调用该函数.
简单地说,使用事件的基本方法就是+=函数名.
在VisualStudio中编写代码时,在对象后面输入点后,系统会智能提示出它所有的属性、方法和事件.
在事件名后面输入+=再连续按两次Tab键,系统会自动生成一个函数名及其函数头,我们就可以在函数中填写事件的处理代码了.
总之,对象的三个基本要素是属性、方法和事件,在VisualStudio中处理属性、方法、事件都是很方便的.
1.
2.
4C#程序的基本构成C#的程序可以很简单,也可以很复杂.
下面就C#程序的常见成分进行一个初步的介绍.
一个程序可由一个至多个C#源程序文件构成,每个文件中可以有多个类定义.
下面的程序是一个更一般的C#程序文件.
例12一个简单的窗口程序1usingSystem;2usingSystem.
Drawing;3usingSystem.
Windows.
Forms;4namespacech015{6publicclassHelloWorldWin:System.
Windows.
Forms.
Form7{8publicHelloWorldWin()9{10InitializeComponent();11}12privatevoidInitializeComponent()13{14this.
ClientSize=newSystem.
Drawing.
Size(200,180);15this.
Name="HelloWorldWin";16this.
Text="HelloWorldWin";17this.
Paint+=newSystem.
Windows.
Forms.
PaintEventHandler(18this.
HelloWorldWin_Paint);19}20staticvoidMain()21{22Application.
Run(newHelloWorldWin());23}24privatevoidHelloWorldWin_Paint(25objectsender,System.
Windows.
Forms.
PaintEventArgse)26{27e.
Graphics.
DrawString("Hello,world",28newFont("CuriorNew",12f),29newSolidBrush(Color.
Blue),3050f,100f,null);31}32}33}这个程序与上一个例子相似,但它是手工书写的.
下面来分析这个程序的组成:从这个例子可以看出,一般的C#源程序文件由以下三部分组成:using语句类型定义namespace其中,using语句表示引入其他类的库,以方便使用.
using语句可以有0到多句,它必须放在类型定义的前面.
namespace,表示类所在的名字空间.
namespace的花括号{}内,可以嵌套一些using语句、类型定义或者namespace.
每个文件都可以包含多个类型定义、多个名字空间.
在一个C#程序中,可以通过一个元素的完整名称来识别它,这个名称表明出层次关系.
例如,System.
String是字符串类型完整的名称.
但是为了简化代码起见,只要声明正在使用System名字空间:usingSystem;就可以使用一个相对名称如String来作为完整名称的同义词,而最后依然代表System.
String.
类型定义是C#源程序的主要部分,每个文件中可以定义若干个类型.
类型的定义可以位于名字空间之内,也可以位于名字空间之外.
类型定义中,最主要的就是类的定义.
C#程序中定义类使用关键字class,每个类的定义由类头定义和类体定义两部分组成.
类头部分除了声明类名之外,还可以说明类的继承特性,当一个类被定义为是另一个已经存在的类(称为这个类的父类)的子类时,它就可以从其父类中继承一些已定义好的类成员.
类体部分用来定义属性和方法等成分,它们称为类的成员.
在类体中通常有两种成员,一种是域,包括变量、常量、对象数组等独立的实体;另一种是方法,是类似于函数的代码单元块.
在上面的例子中,类HelloWorldWin中只有4个类成员,包括方法Main.
用来标志方法头的是一对小括号,在小括号前面并紧靠左括号的是方法名称,如Main等;小括号里面是该方法使用的形式参数,方法名前面是用来说明这个方法属性的修饰符,其具体语法规定将在后面介绍.
方法体部分由若干以分号结尾的语句组成并由一对大括号括起,在方法体内部不能再定义其他的方法.
同其他高级语言一样,语句是构成C#程序的基本单位之一.
每一条C#语句都由分号(;)结束,其构成应该符合C#的语法规则.
类和方法中的所有语句应该用一对大括号{}括起.
除using及namespace语句之外的其他的执行具体操作的语句,都只能存在于类的大括号之中.
比语句更小的语言单位是表达式、变量、常量和关键字等,C#的语句就是由它们构成的.
其中关键字是C#语言语法规定的保留字,用户程序定义的常量和变量的取名不能与保留字相同.
C#源程序的书写格式比较自由,如语句之间可以换行,也可以不换行,但养成一种良好的书写习惯比较重要.
特别注意的是,C#是大小写严格区分的语言.
书写时,大小写不能混淆.
同一个C#程序中定义的若干类之间没有严格的逻辑关系要求,但它们通常是在一起协同工作的,每一个类都可能需要使用其他类中定义的属性或方法.
一个程序中只有一个程序入口,即一个Main方法,如果有多个Main()方法,则在编译时要指定程序的入口.
如果使用VisualStudiou新建项目,则系统会自动生成一个Program.
cs它其中含有Main(),对于Windows应用程序,Main()如下:staticclassProgram{//////应用程序的主入口点.
///[STAThread]staticvoidMain(){Application.
EnableVisualStyles();Application.
SetCompatibleTextRenderingDefault(false);Application.
Run(newForm1());}}其中的方键语句是Application.
Run(newForm1());也就是创建(new)并运行窗体.
以上介绍的是程序的基本成分,它们之间的关系可以表示为:程序包含多个.
cs文件;每个.
cs文件包含0个至多个名字空间(namespace);每个名字空间包含多个类(class)的定义;每个类中含有多个变量及方法;每个方法中含有局部变量定义及语句.
1.
3程序中的输入输出及运算输入输出是程序的基本功能,本节将介绍如何编写具有基本输入输出功能的C#程序,C#程序的输入输出可以是文本界面,也可以是图形界面.
1.
3.
1控制台应用程序的输入输出控制台应用程序也就是字符界面的应用程序.
在字符界面中,用户用字符串向程序发出命令传送数据,程序运行的结果也用字符的形式表达.
字符界面的输入输出要用到System.
Console来表示输入及输出,System.
Console的Read()方法可以输入一个字符(但要注意此方法直到读取操作终止,例如用户按下Enter键后才会返回),ReadLine()方法可以输入一行字符串,System.
Console的Write()方法可以输出一个数据或一个字符串,字符串之间或字符串与其他变量间可以用加号(+)表示连接.
System.
Console的WriteLine()方法可以输出一个字符串并换行.
如下例,输入一个字符,并显示这个字符.
例13AppCharInOut.
cs字符的输入输出1usingSystem;2publicclassAppCharInOut3{4publicstaticvoidMain(string[]args)5{6charc='';7System.
Console.
Write("Pleaseinputachar:");8c=(char)System.
Console.
Read();9Console.
WriteLine("Youhaveentered:"+c);10}11}运行结果如所示.
图117字符的输入输出System.
Console的Read方法只能读入一个字符,不便于使用,下面的例子中ReadLine方法,可用于读入一串字符.
下面的例子读入一串字符并显示它.
例14AppLineInOut.
cs整行的输入输出1usingSystem;2publicclassAppLineInOut3{4publicstaticvoidMain(string[]args)5{6strings="";7Console.
Write("Pleaseinputaline:");8s=Console.
ReadLine();9Console.
WriteLine("Youhaveentered:"+s);10}11}运行结果如图118所示.
图118整行的输入有时,还需要将输入的字符串转成数字(如整数int或实数double),这时,可用int.
Parse()及double.
Parse()方法,也可以写为Int32.
Parse()及Double.
Parse()如下例所示.
例15AppNumInOut.
cs数字的输入输出1usingSystem;2publicclassAppNumInOut3{4publicstaticvoidMain(string[]args)5{6strings="";7intn=0;8doubled=0;9Console.
Write("Pleaseinputanint:");10s=Console.
ReadLine();11n=Int32.
Parse(s);12Console.
Write("Pleaseinputadouble:");13s=Console.
ReadLine();14d=Double.
Parse(s);15Console.
WriteLine("Youhaveentered:"+n+"and"+d);16}17}运行结果如所示.
图119数字的输入输出在C#程序中使用Console.
Write()或Console.
WriteLine()时,还有以下两种知识经常用到:(1)如果有多项信息,信息之间可以用加号(+)连接起来,以表示形成一个字符串.
例如:"Youhaveentered:"+n+"and"+d(2)若在字符串有变量,还可以在字符串中用{0}、{1}、{2}等分别表示各个变量.
例如:Console.
WriteLine("Youhaveentered:{0}and{1}.
",n,d);(3)在C#6.
0以上的版本中,还可以直接使用{变量名或表达式}嵌入到格式串中,这要求格式串前面写一个$符号.
例如:Console.
WriteLine($"Youhaveentered:{n}and{d}.
");这种方式称为字符串嵌入值(stringinterpolation),它比较直观而且不容易错.
这实际是一个语法糖(syntexsuger),也就是说C#编译器会将这种简写方式翻译成复杂的语法元素,字符串嵌入值实际上翻译成了字符串的加号连接(而加号连接又翻译成了字符串的Append方法).
随着C#语言的发展,C#语言中增加了大量的语法糖,极大地方便了代码的书写,但给初学者增加了负担,我们会在不同的章节提到这些语法糖.
1.
3.
2Windows应用程序输入输出Windows应用程序用图形界面的,其基本的输入输出手段是使用界面上的对象(也称为"控件"),例如:使用文本框对象(TextBox)获取用户输入的数据,使用标签对象(Label)或文本框对象输出数据,使用命令按钮(Button)来执行命令.
图形界面的程序最好借助于集成开发工具(如VisualStudio)来实现.
例16WinInOut.
cs图形界面输入输出.
1usingSystem;2usingSystem.
Windows.
Forms;3usingSystem.
Drawing;4publicclassWinInOut:Form5{6TextBoxtxt=newTextBox();7Buttonbtn=newButton();8Labellbl=newLabel();910publicvoidinit()11{12this.
Controls.
Add(txt);13this.
Controls.
Add(btn);14this.
Controls.
Add(lbl);15txt.
Dock=System.
Windows.
Forms.
DockStyle.
Top;16btn.
Dock=System.
Windows.
Forms.
DockStyle.
Fill;17lbl.
Dock=System.
Windows.
Forms.
DockStyle.
Bottom;18btn.
Text="求平方";19lbl.
Text="用于显示结果的标签";20this.
Size=newSize(300,120);2122btn.
Click+=newSystem.
EventHandler(this.
button1_Click);23}2425publicvoidbutton1_Click(objectsender,EventArgse)26{27strings=txt.
Text;28doubled=double.
Parse(s);29doublesq=d*d;30lbl.
Text=d+"的平方是:"+sq;31}3233staticvoidMain()34{35WinInOutf=newWinInOut();36f.
Text="WinInOut";37f.
init();38Application.
Run(f);39-+}40}在本程序中,生成了一个文本框txt用于输入,一个标签lbl用于输出,一个按钮btn用于触发命令.
在init(初始化)方法中,将这三个对象加入.
在程序中,还有一点很关键,就是加入一个事件处理程序,其作用是当用户点击此按钮时,通过Text方法得到用户的输入,然后用double.
Parse()方法转为一个实数(double),再计算其平方,用Label的Text显示其平方值,如图120所示.
图120图形界面输入输出1.
3.
3常用的运算在程序中,可以使用基本的运算,如+、-、*、/,而且一些基本的写法与C、C++、Java等相似,下章将会详细介绍.
这里介绍几个基本的类,以方便我们编写一些简单的程序.
Math类:是关于数学运算的类,有一系列方法可用,如Math.
Sqrt()表示平方根,Math.
Round()表示四舍五入,Math.
Log()表示自然对数,Math.
Pow()表示幂运算,Math.
Sin()表示正弦等等.
Random类:表示随机数.
如:Randomrnd=newRandom();intn=rnd.
Next(10);doubled=rnd.
NextDouble();这里生成了一个随机数对象,用其Next(10)方法得到一个0到9的随机整数,而用NextDouble()则得到一个随机小数(0到1之间).
Convert类:表示转换.
它可以方便地将输入的字符串转成别的类型:intn=Convert.
ToInt32("123");doubled=Convert.
ToDouble("123.
45");其中分别转成整数和小数.
在VisualStudio中,可以方便地查看这些类及方法,一方面在输入过程中系统会自动提示;另一方面将输入点置于一个单词上,然后按F1键,系统会自动打开帮助信息(要求联网),即打开.
NETFrameworkAPI文档,如图121所示,可以从中查看详细的说明.
图121查看API文档1.
4开发工具前面多次提到了VisualStudio开发工具,也提到了控制台、Windows两种应用程序,为了更全面的了解,本节介绍更多的开发工具、更多的应用程序类型.
1.
4.
1.
NETFrameworkSDK及VisualStudio正如第1.
1节所提到的,C#的主要环境是Microsoft.
NETFramework,在该环境中,提供了一系列的开发工具,称为.
NETFrameworkSDK.
Microsoft.
NETFrameworkSDK是免费的,可以从以下站点下载https://www.
microsoft.
com/net/targeting要提醒的是,SDK是开发环境.
如果不编译C#程序,只运行程序,可以只安装.
NETFramework的运行环境,这样可以占用较少的磁盘空间.
不过,一般地Windows操作系统上已经自带了.
NETFramework运行环境.
现在.
NETFrameworkSDK直接包含在VisualStudio中了,所以可以直接安装VisualStudio而得到SDK.
现在Microsoft提供了VisualStudio的社区版(免费)、专业版、企业版,对于学习者而言,社区版(community)的功能已经足够强大,可以从以下站点下载https://www.
visualstudio.
com下载VisualStudio后就可以安装,在安装时,我们可以选择需要的Workload(工作负荷),对于初学者而言序,只要选择".
NET桌面开发"就可以了,以后需要其他的,可以随时安装(再次运行安装程序VisualStudioInstaller).
1.
4.
2使用命令行编译及运行程序一般高级语言编程需要经过源程序编辑、目标程序编译生成和可执行程序运行几个过程,C#编程也不例外,本节就编辑、编译、运行C#程序的一般步骤进行介绍.
尽管可以使用VisualStudio集成开发环境来开发复杂的项目,但本书中大部分示例程序可以使用命令行来进行编译和运行.
1.
程序的编辑C#源程序是以.
cs为后缀的简单的文本文件,可以用各种C#集成开发环境中的源代码编辑器来编写,也可以用其他文本编辑工具,如Windows中的记事本等.
以简单的记事本(Notepad)软件为例,打开记事本,输入下面一段程序:usingSystem;publicclassHelloWorld{//anapplicationpublicstaticvoidMain(string[]args){Console.
WriteLine("HelloWorld!
");}}程序输入并修改完毕,要将此文件保存,在保存文件时,要注意,文件的类型要选"所有类型",文件名文件名可以为HelloWorld.
cs.
如果使用其他编辑器,也要注意保存时以纯文本方式进行保存,并且将文件扩展名定为.
cs文件.
提示:本书中的示例程序可以在附带的电子资源中获得,但对于初学者,手工输入程序并调试运行是一种很好的学习方式.
2.
程序的编译与其他语言一样,源程序(.
cs文件)要经过编译(compile)才能运行.
编译的过程实际上是将C#源程序转变为可执行文件,扩展名为.
exe,其中包含的是程序的指令.
(如前面所说,这里.
exe文件包含的是IL指令和元数据,只有在实际运行时,才会即时地转成机器的CPU指令并执行.
)编译可以使用工具csc.
exe.
该工具的使用方法如下:1)进入命令行环境,方法是:选"开始"/"运行",然后键入cmd2)然后进入到存放源文件的目录(假定是d:\CsExample\ch01目录),运行d:cdd:\CsExample\ch013)编译源程序,键入cscHelloWorld.
cscsc后面可以跟C#源程序文件名,文件名可以有多个,还可以用*及通配符,如:cscHello*.
cscsc还可以跟一系列选项,为了查看其选项,可以用csc/来查看,结果如下:在以上选项中,比较重要的是:/out:输出文件名(默认值:包含主类的文件或第一个文件的基名称)/target:exe生成控制台可执行文件(默认)(缩写:/t:exe)/target:winexe生成Windows可执行文件(缩写:/t:winexe)/unsafe[+|-]允许"不安全"代码当编译成功后,csc会产生相应的.
exe文件.
若编译不成功,csc会提示信息,根据此信息,读者可进一步修改源程序,再重新编译.
为了使用csc命令,需要设置环境变量,这个设置过程较复杂,稍后面专门讲解.
3.
程序的运行程序的运行就是执行.
exe文件中的指令的过程.
在上面的例子中,运行所编译好的程序,用命令:HelloWorld程序的运行结果如图122所示.
图122HelloWorld程序运行结果在Windows中,也可以在资源管理器中双击此.
exe文件,即可以运行程序.
4.
设定path环境变量如上所述,在编译及运行时,经常需要设定path这个环境变量.
值得注意的是,随着Microsoft技术的演进,csc工具(csc.
exe)所用的技术、所在的目录(文件夹)也在发生变化,例如:早期csc.
exe在C:\WINNT\Microsoft.
NET\Framework\v1.
0.
3705\目录下;在.
NET2.
0时期在C:\WINNT\Microsoft.
NET\Framework\v2.
0.
50727\下;在4.
0版本中,则在C:\Windows\Microsoft.
NET\Framework64\v4.
0.
30319;安装VisualStudio2015后,其中附带安装的MSBuild编译平台中的csc.
exe则可能在C:\ProgramFiles(x86)\MSBuild\14.
0\Bin目录下;安装VisualStudio2017后,其中附带安装的MSBuild编译平台中使用Roslyn编译服务的csc.
exe则可能在C:\ProgramFiles(x86)\MicrosoftVisualStudio\2017\Community\MSBuild\15.
0\Bin\Roslyn目录下;在跨平台环境(.
NETcore)中,csc则可能在C:\ProgramFiles\dotnet\sdk\1.
0.
3\Roslyn中.
你可以在自已的电脑中搜索一下csc.
exe看看其所在的目录.
以MSBuild编译平台为例,为了能使用csc.
exe可以写全路径C:\ProgramFiles(x86)\MSBuild\14.
0\Bin\cscHelloWorld.
cs为了省略其所在目录,可以先键入设置path环境变量的命令Setpath=C:\ProgramFiles(x86)\MSBuild\14.
0\Bin;%path%这样,编译命令可以直接写csc,如:cscHello*.
cs为了长期设置path环境变量,可以在"我的电脑"("此电脑")右击,选"属性|高级系统设置|环境变量",在系统变量中,选择"path",然后点击"编辑""新建",就可以在path中增加一项,写上csc.
exe所在的目录即可.
如图123所示.
图123编辑环境变量5.
处理程序的语法错误在程序编辑的过程中,通常容易出现错误,最常见的是字母大小写不对,输错某个字符等等.
对于有错误的程序,编译时会报告一个语法错误(syntaxerror).
在用csc进行编译时,报告的语法错一般具有以下格式源程序名(行号,列号):error错误号:错误信息例如:HelloWorld.
cs(8,27):errorCS1002:应输入;根据这些信息,可以进一步对源程序进行修改.
在实际编译时,C#编译器会试图根据源代码来理解程序的意图,由于这个原因,报告的错误并不能总是反映问题的实际情况.
为了找到出错的真正原因,编程者需要再进行猜测,或是看一看出错的那行代码的附近的几行代码.
1.
4.
3辅助工具EditPlus在实际编程时,还可以借助一些辅助工具来加快程序的设计.
在C#的辅助工具中,有许多是比较小巧的,它们的主要功能有两点:(1)提供一个编辑器,能编辑C#程序及Html文件;(2)用菜单或快捷键方便地调用csc和生成的exe文件来编译和运行C#程序.
这样的辅助工具主要有:EditPlus,UltraEditor等.
它们是免费软件或共享软件,可以从网上下载后安装并使用.
当然在安装这些软件工具之前,系统中必须首先安装.
NETFrameworkSDK.
下面以共享软件EditPlus为例,它的主要功能是文本编辑,对编辑C#程序及Html网页也有较好的支持.
在编辑时,对于一些重要的关键词还以醒目的颜色显示出来,这样可以使阅读程序更加方便,也有助于减少键入错误.
如果要下载最新版本的EditPlus可以访问网站:http://www.
editplus.
com在下载时,一方面要下载EditPlus运行程序,还要下载editplus的插件——即C#(Csharp)的语法文件.
先安装EditPlus,再安装语法文件.
安装语法文件的步骤是:(1)选Tools(工具)Preference(首选项)Files(文件)SettingsandSyntax(设四置和语法),在其中加入文件类型(Csharp),设定其扩展名为cs,并设定语法文件为下载的语法文件,如图124所示.
图124加入文件类型(2)要新建一个程序,选FileNewOthersCSharp即可.
图125EditPlus界面EditPlus界面如图125所示.
左边为文件夹及文件的显示区,中间为编辑窗口,下边为信息窗口.
为了方便在EditPlus中调用编译及运行功能,需要进行设置UserTools(用户工具).
选择菜单"Tools/ConfigureUserTools",在弹出的对话框中,点"Add"加入用户工具,如图126所示.
图126设置UserTools对于编译及运行分别设置如下:表12设置UserTools的值选项针对编译的设置针对运行的设置MenutextCompileC#RunC#CommandC:\ProgramFiles(x86)\MicrosoftVisualStudio\2017\Community\MSBuild\15.
0\Bin\Roslyn\csc.
execmd/cArgument$(FileName)$(FileNameNoExt).
exeInitialdirectory$(FileDir)$(FileDir)Captureoutput(选择)(不选择)设置好以后,用户可以用以下方式来使用:使用菜单FileNewOthers中选择Csharp文件,即可新建一个C#文件,然后开始编辑;按快捷键Ctrl+S(或使用菜单FileSave)保存文件;按快捷键(如:Ctrl+1)来进行编译;按快捷键(如:Ctrl+2)来运行程序.
当然用户也可以只用EditPlus来编辑程序,然后,在命令行状态下用csc的命令进行编译,用生成的exe文件来运行.
1.
4.
4辅助工具VisualStudioCodeMicrosoft提供了开源、免费的编辑工具VisualStudioCode,可以从以下网站下载https://code.
visualstudio.
com/VisualStudioCode是一个跨平台的文本编辑工具,可以方便编写C#程序、网页文件、Javascript脚本等,并且在Windows、Linux、MacOSX上都可以使用.
如图127VisualStudioCode图127所示.
图127VisualStudioCode在VisualStudioCode中,按Ctrl+`可以进入控制台(又叫终端),在其中可以输入编译命令及运行程序.
如果安装dotnetcore开发工具,还可以进行C#程序的调试.
具体可参见https://github.
com/dotnet.
1.
5应用程序类型1.
5.
1VisualStudio建立不同类型的应用程序编写C#应用程序最方便当然是使用VisualStudio,它是Microsoft新一代的集成开发环境.
其中有针对多种编程语言(包括C#,C++,VB,F#,JavaScript,Python等)的代码编辑器.
而且这个环境中还具HTML编辑器、XML编辑器、SQLServer界面以及ServerExplorer.
这个在环境还可以方便调试、文档生成等辅助开发工作.
总之,VisualStudio.
一个功能强大的集成开发环境(IDE).
在VisualStudio可以建立各个项目类型,这些项目可以用各种语言来实现.
以C#语言所能建立的类型也有很多种,如图128所示.
图128VisualStudio能建立各种类型的项目而常见的项目类型如表13所示.
表13常见的项目类型项目类型项目说明控制台应用程序此项目类型用于创建命令行实用工具和应用程序.
程序的输入和输出是通过基于文本的终端窗口进行的.
Windows应用程序此项目类型用于创建Windows客户端应用程序.
项目创建一个Windows窗体,可以在该窗体上放置其他控件、显示文本和图形.
WPF应用程序此项目类型用于创建WPF客户端应用程序.
项目创建一个WPF窗体,可以在该窗体上放置其他控件、显示文本和图形.
Windows服务程序此项目类型用于创建Windows服务程序.
项目创建一个Windows服务,可以在控制面板的服务中进行管理.
Web应用程序此项目类型用于创建ASP.
NETWeb应用程序.
Web应用程序运行在网络上,可以通过浏览器来访问.
.
NETCore应用程序使用跨平台的.
NETCore而不是.
NETFramewok来作为运行环境.
.
NETCore大部分的类与.
NETFramework是兼容的,但.
NETCore没有Windows界面,而使用ASP.
NETCore的Web界面.
类库类库项目创建一个库文件,它可用来存储类库(.
dll文件)以供在其他应用程序中引用.
空项目此选项创建一个不包含任何文件的项目.
可以手工加入代码及引用别的类库.
各种项目的差别在于运行环境的不同,所使用的界面也不同,但是所使用的底层技术,如C#语言机制、基本类库、文件输入输出、文本图像信息的处理、数据库访问技术都是一样的,本书的主要内容也是这些基本的技术,所以对各种项目类型都是适用的.
本书中用到的主要项目类型有两种,一是控制台应用程序,一是Windows窗体应用程序,在1.
2节中也主要介绍的这两种项目的建立和运行方法.
考虑到读者的不同需求,这里简单地介绍一下WPF和Web应用程序.
1.
5.
2WPF应用程序WPF(WindowsPresentationFoundation)是微软推出的基于Windows的用户界面框架,是.
NETFramework3.
0以上版本开始提供的.
WPF应用程序,也是Windows图形化界面的应用程序,与Windows窗体应用程序很相似,建立WPF应用程序的步骤也很相似,它里面的界面对象的放置、属性的设置、事件代码的书写也几乎一样,如图129所示.
图129WPF应用程序WPF应用程序与Windows窗体应用程序最大的不同之处在于:WPF设计的界面是用一个.
xaml文件来描述的.
.
xaml文件是一种有特殊格式的XML文件,其中用文本的方式描述了界面的对象及其属性、事件,也就是说它的界面用描述性的,而前面讲到的Windows窗体应用程序中,其界面设计是用一个.
designer.
cs文件,用C#代码来描述的.
WPF程序比Windows窗体程序具有一些优点,比如.
xaml文件可以由美工设计师来书写,与程序代码可以实现相好的分离,另外,WPF界面中可以不用代码来实现渐变颜色等更效果(这在Windows窗体中要写较多的代码).
但是WPF的.
xaml实际又是一种"语言",它有很多的语法及标记需要学习和掌握,对于初学者而言,这个挑战是很大的.
基于这种考虑,我们在本书中主要以控制台和Windows窗体应用程序来讲解,使读者更加专注于C#语言及基础应用的学习.
要提醒读者的是:在简单的情况下,WPF应用程序与Windows窗体应用几乎是一样的,读者完全可以使用WPF来学习所有的例子.
本书的配套电子资源提供了全书中所有的Windows窗体应用程序示例所对应WPF版本的代码,可以对照学习.
限于篇幅,WPF代码就不列在纸质书中了.
1.
5.
3Web应用程序Web应用程序,是在网络上应用的程序,程序的代码运行在服务端,而使用浏览器来访问它,可以简单地说,Web应用程序是以浏览器来作为其输入输出的界面的.
Web应用程序的项目又可以细分为好几种,依其运行环境,又分为ASP.
NET或ASP.
NETcore两种,前者是运行于.
NETFramework中,后者是运行于跨平台.
NETCore框架中的.
Web应用程序中也有对象及其属性、方法、事件的概念,但其界面是网页,也是一种特殊的HTML文本来描述的,如图130所示.
图130Web应用程序Web项目会涉及更多的技术,如HTML、CSS、Javascript等,这已超出本书的范围内.
不过,本书学到的C#及相关知识完全可以应用到Web项目中.
1.
6面向对象程序设计的基本概念C#是面向对象的程序设计语言,面向对象的软件开发和是当今计算机技术发展的重要成果和趋势之一.
本节介绍面向对象软件开发和面向对象程序设计中的基本概念和基本方法,使读者对面向对象软件开发方法的体系、原则、基本思想和特点有—定的了解.
对于初学者,可以略过此节,等学过一段时间再回头来看看比较抽象一些的描述.
1.
6.
1面向对象概述不同于面向过程的程序设计中以具体的解题过程为研究和实现的主体,面向对象的程序设计(OOP)是以需解决的问题中所涉及到的各种对象为主要矛盾.
在面向对象的方法学中,"对象"是现实世界的实体或概念在计算机逻辑中的抽象表示.
具体地,对象是具有唯一对象名和固定对外接口的一组属性和操作的集合,用来模拟组成或影响现实世界问题的一个或一组因素.
其中对象名是区别于其他对象的标志;对外接口是对象在约定好的运行框架和消息传递机制中与外界通信的通道;对象的属性表示了它所处于的状态;而对象的操作则用来改变对象的状态达到特定的功能.
对象的最主要特点是以数据为中心,它是一个集成了数据和其上操作的独立、自恰的逻辑单位.
面向对象的问题求解就是力图从实际问题中抽象出这些封装了数据和操作的对象,通过定义属性和操作来表述它们的特征和功能,通过定义接口来描述它们的地位及与其他对象的关系,最终形成一个广泛联系的可理解、可扩充、可维护、更接近于问题本来面目的动态对象模型系统.
面向对象的程序设计将在面向对象的问题求解所形成的对象模型基础之上,选择一种面向对象的高级语言来具体实现这个模型.
相对于传统的面向过程的程序设计方法,面向对象的程序设计具有如下的优点:(1)对象的数据封装特性彻底消除了传统结构方法中数据与操作分离所带来的种种问题,提高了程序的可复用性和可维护性,降低了程序员保持数据与操作相容的负担.
(2)对象的数据封装特性还可以把对象的私有数据和公共数据分离开,保护了私有数据,减少了可能的模块间干扰,达到降低程序复杂性、提高可控性的目的.
(3)对象作为独立的整体具有良好的自恰性,即它可以通过自身定义的操作来管理自己.
一个对象的操作可以完成两类功能,一是修改自身的状态,二是向外界发布消息.
当一个对象欲影响其他的对象时,它需要调用其他对象自身的方法,而不是直接去改变那个对象.
对象的这种自恰性能使得所有修改对象的操作都以对象自身的一部分的形式存在于对象整体之中,维护了对象的完整性,有利于对象在不同环境下的复用、扩充和维护.
(4)在具有自恰性的同时,对象通过一定的接口和相应的消息机制与外界相联系.
这个特性与对象的封装性结合在一起,较好地实现了信息的隐藏.
即对象成为一只使用方便的"黑匣子",其中隐藏了私有数据和细节内容.
使用对象时只需要了解其接口提供的功能操作即可,而不必了解对象内部的数据描述和具体的功能实现.
(5)继承是面向对象方法中除封装外的另一个重要特性,通过继承可以很方便地实现应用的扩展和已有代码的重复使用,在保证质量的前提下提高了开发效率,使得面向对象的开发方法与软件工程的新兴方法——快速原型法很好地结合在一起.
综上所述,面向对象程序设计是将数据及数据的操作封装在一起,成为一个不可分割的整体,同时将具有相同特征的对象抽象成为一种新的数据类型——类.
通过对象间的消息传递使整个系统运转.
通过对象类的继承提供代码重用的有效途径.
在面向对象程序设计方法中,其程序结构是一个类的集合和各类之间以继承关系联系起来的结构,有一个主程序,在主程序中定义各对象并规定它们之间传递消息的规律.
从程序执行这一角度来看,可以归结为各对象和它们之间的消息通信.
面向对象程序设计最主要的特征是各对象之间的消息传递和各类之间的继承.
1.
6.
2对象、类与实体1.
对象对象的概念是面向对象技术的核心所在.
以面向对象的观点看来,所有的面向对象的程序都是由对象来组成的,这些对象首先是自治、自恰的,同时它们还可以互相通信、协调和配合,从而共同完成整个程序的任务和功能.
更确切地,面向对象技术中的对象就是现实世界中某个具体的物理实体在计算机逻辑中的映射和体现.
比如,电视机是一个具体存在的,拥有外形,尺寸、颜色等外部特性和开关、频道设置等实在功能的实体;而这样一个实体,在面向对象的程序中,就可以表达成一个计算机可理解、可操纵、具有一定属性和行为的对象.
类也是面向对象技术中一个非常重要的概念.
简单地说,类是同种对象的集合与抽象.
类是一种抽象的数据类型,它是所有具有一定共性的对象的抽象,而属于类的某一个对象则被称为是类的一个实例,是类的一次实例化的结果.
如果类是抽象的概念,如"电视机",那么对象就是某一个具体的电视机,如"我家那台电视机".
2.
对象的状态与行为对象都具有状态和行为.
对象的状态又称为对象的静态属性,主要指对象内部所包含的各种信息,也就是变量.
每个对象个体都具有自己专有的内部变量,这些变量的值标明了对象所处的状态.
当对象经过某种操作和行为而发生状态改变时,具体地就体现为它的属性变量的内容的改变.
通过检查对象属性变量的内容,就可以了解这个对象当前所处于的状态.
仍然以电视机为例.
每一个电视机都具有以下这些状态信息:种类、品牌、外观、大小、颜色、是否开启、所在频道等.
这些状态在计算机中都可以用变量来表示.
行为又称为对象的操作,它主要表述对象的动态属性,操作的作用是设置或改变对象的状态.
比如一个电视机可以有打开、关闭、调整音量、调节亮度、改变频道等行为或操作.
对象的操作一般都基于对象内部的变量,并试图改变这些变量(即改变对象的状态).
如"打开"的操作只对处于关闭状态的电视机有效,而执行了"打开"操作之后,电视机原有的关闭状态将改变.
对象的状态在计算机内部是用变量来表示,而对象的行为在计算机内部是用方法来表示的.
方法实际上类似于面向过程中的函数.
对象的行为或操作定义在其方法的内部.
3.
对象的关系一个复杂的系统必然包括多个对象,这些对象间可能存在的关系有三种:包含、继承和关联.
(1)包含当对象A是对象B的属性时,称对象B包含对象A.
例如,每台电视机都包括一个显像管.
当把显像管抽象成一个计算机逻辑中的对象时,它与电视机对象之间就是包含的关系.
当一个对象包含另一个对象时,它将在自己的内存空间中为这个被包含对象留出专门的空间,即被包含对象将被保存在包含它的对象内部,就像显像管被包含在电视机之中一样,这与它是电视机组成部分的地位是非常吻合的.
(2)继承当对象A是对象B的特例时,称对象A继承了对象B.
例如,黑白电视机是电视机的一种特例,彩色电视机是电视机的另一种特例.
如果分别为黑白电视机和彩色电视机抽象出黑白电视机对象和彩色电视机对象,则这两种对象与电视机对象之间都是继承的关系.
实际上,这里所说的对象间的继承关系就是后面要详细介绍的类间的继承关系.
作为特例的类称为子类,而子类所继承的类称为父类.
父类是子类公共关系的集合,子类将在父类定义的公共属性的基础上,根据自己的特殊性特别定义自己的属性.
例如彩色电视机对象除了拥有电视机对象的所有属性之外,还特别定义了静态属性"色度"和相应的动态操作"调节色度".
(3)关联当对象A的引用是对象B的属性时,称对象A和对象B之间是关联关系.
所谓对象的引用是指对象的名称、地址、句柄等可以获取或操纵该对象的途径.
相对于对象本身,对象的引用所占用的内存空间要少得多,它只是找到对象的一条线索.
通过它,程序可以找到真正的对象,并访问这个对象的数据,调用这个对象的方法.
例如,每台电视机都对应一个生产厂商,如果把生产厂商抽象成厂商对象,则电视机对象应该记录自己的生产厂商是谁,此时电视机对象和厂商对象之间就是关联的关系.
关联与包含是两种不同的关系.
厂商并不是电视机的组成部分,所以电视机对象里不需要也不可能保存整个厂商对象,而只需要保存一个厂商对象的引用,例如厂商的名称.
这样,当需要厂商对象时,如当需要从厂商那里购买一个零件时,只需要根据电视机对象中保存的厂商的名字就可以方便地找到这个厂商对象.
1.
6.
3封装、继承、多态所有的面向对象的编程语言,包括C#在内,都有3个最基本的共同特点:封装、继承和多态性.
1.
封装封装(Encapsulation)是这样一种编程机制,它把代码和其操作的数据捆绑在一起,从而防止了外部对数据和代码的干扰和滥用,保证了数据和代码的安全性.
OO语言通过创建"自包含的暗箱"实现代码和数据的捆绑.
暗箱中包含所有必要的数据和代码.
代码和数据以这种方式链接起来就创建了一个对象.
换句话说,对象是一种支持封装的设备.
在一个对象中,代码、数据或者两者都可以是该对象私有的(private),也可以是公共的(public).
私有代码或数据只能被本对象内部的其他部分可见和可访问.
也就是说,私有代码或数据不能被对象以外的程序块所访问.
如果代码或数据是公共的,程序的其他部分就可以访问它,即使它们被定义在对象中.
典型的做法是,对象的公共部分用来提供一个访问该对象私有元素的受控接口.
C#封装的基本单位是"类"(class),类定义对象的格式.
它规定数据和操作数据的代码.
C#使用类来规范构建对象.
对象是类的实例.
所以说,类的本质就是一套规定如何创建对象的计划.
组成类的代码和数据叫做类的成员.
具体地说,类中定义的数据叫做类的"成员变量"或者"实例变量".
操作数据的代码叫做"成员方法"或"方法".
方法在C#中指的是一个子过程,或称"函数".
2.
继承继承(Inheritance)是一个对象获得另一个对象的属性的过程.
它的重要性源于它支持按层次分类概念.
这与现实世界是一致的,大多数知识因为层次化分类而变得容易掌握(即从上至下).
例如,红色、美味的苹果属于苹果类,而苹果类又属于水果类,并且最终属于食物这个大类.
食物类拥有许多属性(可以吃,有营养等),逻辑上也适用于它的子类——水果.
除了这些性质以外,水果类还有许多特殊的性质(多汁,甜等等)以使它区别于其他的食物.
苹果类定义了苹果所独有的属性(长在树上,不生长在热带等等).
红色、美味的苹果继承了所有这些类,并且定义了那些属于它的特有的属性.
如果不使用继承,每一个对象都必须精确地定义它的全部属性.
使用继承,一个对象可以从它父类继承所有的通用属性,而只需定义它特有的属性.
所以,正是继承机制可以使一个对象成为一个更通用类的一个特例成为可能.
3.
多态性多态性(Polymorphism来自希腊语,意思是多种形态)是指允许一个接口访问动作的通用类的性质.
汽车方向盘就是多态性的一个简单例子.
不论你的汽车是手动转向、动力转向还是齿轮齿条转向,操纵方法都是一样的.
不论什么样的转向系统,向左转动,方向盘将使汽车左转.
当然,这种统一接口的好处是一旦你会开车,你就可以驾驶各种车辆.
同样的规则也适用于编程.
以堆栈(后入先出)为例,可能你的程序需要3种不同的堆栈类型,分别用于整数值、浮点数值和字符.
在这里,虽然堆栈存储数据类型不同,但每个堆栈的算法是相同的.
在非OO语言中,需要创建3组不同名字的堆栈实用程序,但是,由于多态性,在C#中只需创建一套通用的堆栈实用程序来应付3种特定的情况.
一般地,多态性的概念常被解释为"一个接口,多种方法".
这意味着可以为一组相关活动设计一个通用接口.
多态性允许用相同接口规定一个通用类来减轻问题的复杂度.
选择适当的动作(方法)适应不同环境的工作则留给编译器去做.
作为编程者,无需手工去做这些事情,只需利用通用接口即可.
1.
6.
4面向对象的软件开发过程面向对象的软件开发过程可以大体划分为面向对象的分析(ObjectOrientedanalysis,OOA)、面向对象的设计(Objectorienteddesign,OOD)、面向对象的实现(Objectorientedprogramming,OOP)三个阶段.
1.
面向对象的分析面向对象的分析的主要作用是明确用户的需求,并用标准化的面向对象的模型规范地表述这一需求,最后将形成面向对象的分析模型,即OOA模型.
分析阶段的工作应该由用户和开发人员共同协作完成.
需求分析是要抽取存在于用户需求中的各对象实体,分析、明确这些对象实体的静态数据属性和动态操作属性以及它们之间的相互关系;更重要地,要能够反映出由多个对象组成的系统的整体功能和状态,包括各种状态间的变迁以及对象在这些变迁中的作用、在整个系统中的位置等.
需求模型化方法是面向对象的分析中常用的方法.
这种方法通过对需要解决的实际问题建立模型来抽取、描述对象实体,最后形成OOA模型,将用户的需求准确地表达出来.
OOA模型有很多种设计和表达方法,如使用较为广泛的Coad&Yourdon的OOA模型.
2.
面向对象的设计如果说分析阶段应该明确所要开发的软件系统"干什么",那么设计阶段将明确这个软件系统"怎么做".
面向对象的设计将对OOA模型加以扩展并得到面向对象的设计阶段的最终结果:OOD模型.
面向对象的设计将在OOA模型的基础上引入界面管理、任务管理和数据管理三部分的内容,进一步扩充OOA模型.
其中界面管理负责整个系统的人机界面的设计;任务管理负责处理并行操作之类的系统资源管理功能的工作;数据管理则负责设计系统与数据库的接口.
这三部分再加上OOA模型代表的"问题逻辑"部分,就构成了最初的OOD模型.
面向对象的设计还需要对最初的OOD模型做进一步的细化分析、设计和验证.
在"问题逻辑"部分,细化设计包括对类静态数据属性的确定,对类方法(即操作)的参数、返回值、功能和功能的实现的明确规定等;细化验证主要指对各对象类公式间的相容性和一致性的验证,对各个类、类内成员的访问权限的严格合理性的验证,也包括验证对象类的功能是否符合用户的需求.
3.
面向对象的实现面向对象的实现就是具体的编码阶段,其主要任务包括:(1)选择一种合适的面向对象的编程语言,如C++、ObjectPascal、C#等.
(2)用选定的语言编码实现详细设计步骤所得的公式、图表、说明和规则等对软件系统各对象类的详尽描述.
(3)将编写好的各个类代码模块根据类的相互关系集成.
(4)利用开发人员提供的测试样例和用户提供的测试样例分别检验编码完成的各个模块和整个软件系统.
综上所述,面向对象的软件开发可概括为如下的过程:分析用户需求,从问题中抽取对象模型;将模型细化,设计类,包括类的属性和类间相互关系,同时考察是否有可以直接引用的已有类或部件;选定一种面向对象的编程语言,具体编码实现上一阶段类的设计,并在开发过程中引入测试,完善整个解决方案.
由于对象的概念能够以更接近实际问题的原貌和实质的方式来表述和处理这些问题,所以面向对象的软件开发方法比以往面向过程的方法有更好的灵活性、可重用性和可扩展性,使得上述"分析—设计—实现"的开发过程也更加高效、快捷.
即使出现因前期工作不彻底、用户需求改动等需要反馈并修改前面步骤的情况,也能够在以前工作的基础之上从容地完成,而不会陷入传统方法中不得不推翻原有设计、重新考虑数据结构和程序结构的尴尬境地.
DiyVM是一家低调国人VPS主机商,成立于2009年,提供的产品包括VPS主机和独立服务器租用等,数据中心包括香港沙田、美国洛杉矶、日本大阪等,VPS主机基于XEN架构,均为国内直连线路,主机支持异地备份与自定义镜像,可提供内网IP。最近,商家对香港机房VPS提供5折优惠码,最低2GB内存起优惠后仅需50元/月。下面就以香港机房为例,分享几款VPS主机配置信息。CPU:2cores内存:2GB硬...
提速啦(www.tisula.com)是赣州王成璟网络科技有限公司旗下云服务器品牌,目前拥有在籍员工40人左右,社保在籍员工30人+,是正规的国内拥有IDC ICP ISP CDN 云牌照资质商家,2018-2021年连续4年获得CTG机房顶级金牌代理商荣誉 2021年赣州市于都县创业大赛三等奖,2020年于都电子商务示范企业,2021年于都县电子商务融合推广大使。资源优势介绍:Ceranetwo...
公司成立于2021年,专注为用户提供低价高性能云计算产品,致力于云计算应用的易用性开发,面向全球客户提供基于云计算的IT解决方案与客户服务,拥有丰富的国内BGP、三线高防、香港等优质的IDC资源。公司一直秉承”以人为本、客户为尊、永续创新”的价值观,坚持”以微笑收获友善, 以尊重收获理解,以责任收获支持,以谦卑收获成长”的行为观向客户提供全面优质的互...