第2章C#语法基础(一)教学重点C#语言的基本类型C#语言类型分类及其存储的异同装箱与拆箱数据类型转换教学内容通用类型系统值类型引用类型常量和变量装箱和拆箱类型转换教学过程在上一章里接触到了第一个C#应用程序,虽只是简单地在控制台输出了一句问候语,但它却充分体现了VisualStudio2008的易用性及C#语言的特点。理解了C#的用途之后,就可以学习如何使用它。本章将介绍C#的基本语法知识,通过本章学习,读者将了解以下内容:理解C#中的数据类型。理解常量和变量的含义及用法。理解数据类型转换的含义。会运用常用的运算符和表达式。2.1C#数据类型应用任何一种程序语言,需要充分了解它提供的数据类型,这样才能明白它的功能与限制,以便选择合适的数据类型来处理不同的数据。例如在平时生活中,我们会用整数来表达东西的数量,而在工程、金融领域我们要用到很高精度小数。但对计算机来说,数据的含义更要宽泛些,比如说一句话、一个字符等,对计算机来说都是数据。计算机会用不同的方式来处理它遇到的不同类型的数据。2.1.1通用类型系统简介通用类型系统(CommonTypeSystem,CTS)是一个所有.NET语言都支持的数据类型的集合,它定义了如何在运行库中声明、使用和管理类型,确保这些语言可以相互传送数据,体现在.NET语言的互操作性。例如在C#中声明int类型的数据和在VB.NET中声明的Integer类型数据,实际上是通用类型系统中的System.Int32的一个实例。将数据类型内置于.NETFramework中的好处是,可以把所有的基本数据类型看作是支持某些方法的类,例如,要把inti转换成string,可以写如下代码:stringstr=i.toString();在C#语言里,有多种数据类型(Type)。根据数据产生时在内存中存放的方式,.Net将整个系统的数据类型分成两大类——值类型和引用类型。值类型直接包含数据。每个值类型变量都包含有它自己的数据备份,因此对一个值类型变量的操作不会影响其他变量。引用类型包含指向对象实例的引用或指针。两个引用类型的变量可以指向同一个对象实例,因此对一个引用变量的操作会影响其他引用变量。可以通过下面一个例子来加深读者对值类型的引用类型的理解。2.1.2值类型【本节示例参考:\源代码\chapter2\2.1.1\ValueTypeExample】大多数编程语言都提供内置的数据类型(比如整数和浮点数),这些数据类型会在作为参数传递时被复制(也就是说,它们通过值来传递)。在.NET框架中,这些数据类型称为值类型。值类型通常是像整数这样的简单类型。C#中的值类型包含整数型、浮点型、布尔型、字符型等。表2.2列出了预定义的简单值类型。2.1.3引用类型【本节示例参考:\源代码\chapter2\2.1.2\RefTypeExample】引用类型的变量又称为对象,可存储对实际数据的引用。类似于在储物柜里存放的是该物品的地址信息。C#支持两个引用类型,如表2.4所示。2.2常量和变量变量名表示一条信息的名称。其实在之前的程序代码中,已经接触到过变量,比如在上一节示例中使用到的a、b、c等,都是string类型的变量。变量的值在程序运行过程中可以改变。而常量是一旦定义好后,在程序运行过程中其值不变的量。2.2.1变量的声明和初始化C#是一种“强类型”编程语言,在声明变量时必须指明它的数据类型。声明变量的作用之一是告诉编译器要为变量分配多少内存空间。就像要将一个物品存进储物间,应该事先让保管员知道,这个物品有多大,以便分配合适大小的储物柜。大了会浪费空间,小了东西放不下,会造成不必要的错误。声明变量的格式如下:数据类型变量名;比如,下面的代码声明了一个int型的变量i:inti;变量声明后,可在程序运行中,给变量i赋值,或者可以在声明的时候给变量赋初值。一个变量声明以后可以多次赋值。在初始化时对变量赋值采用下面的格式:数据类型变量名=初始值;doubletotal=34.3D;2.2.2变量命名规范及编码规则•在C#中,对变量的命名有一些限制,包括以下规则:•变量名必须以字母开头。•变量只能有字母、数字、下划线。不能包含空格、标点等。且不能由数字开头。•变量名不得与C#中的关键字同名。•变量名不得与C#中的库函数同名。•下面给出了一些合法和不合法的变量名:•string3str;//不合法,以数字开头•floattotalcount;//不合法,变量名包含空格•intprod2;//合法•doubleMain;//不合法,与Main函数同名•doublefloat;//因为float是关键字,不能用作变量名2.2.3变量的作用域【本节示例参考:\源代码\chapter2\2.2.3\ScopeExample】作用域(scope)是指由一个代码块或者语言结构约束起来的分层上下文。简单理解,变量的作用域指可以访问某个变量的代码区域。只有在变量被声明的代码块中,它才能被访问到,一旦程序执行超过某个代码块,则该代码块中声明的所有过程级变量都会越界,不能再被访问到。下面的示例演示了在变量的作用域外访问变量的情形:for(inti=0;i10;i++){Console.WriteLine(i);//i在这个循环里有效}Console.WriteLine(lastvalueofiinloop{0},i);//在循环外输出i的值会出错2.2.4声明和使用常量常量就是值固定不变的量。在C#中,可以用const关键字来声明一个常量。在程序设计中,往往把一些经常用到而值不太可能改变的量定义为常量,而不是直接使用其数值。例如在计算和圆相关的问题时,就可以把圆周率定义常量。常量的声明方式如下:constintPI=3.14;//常量一旦声明,在程序运行中就不能再改变其值注意:和C++不同,在C#中,只能把局部变量和字体段(即类里面定义的变量)声明为常量。常量有如下特征:常量必须在声明时初始化。指定了其值后,就不能再修改了。常量值必须能在编译时用于计算。因皮,不能用从一个变量中提取的值来初始化常量。常量总是静态的(用static关键字修饰)。但事实上,在声明常量的时候不允许包含修饰符。如下面的一组定义:constinti;//错误,没有初始化constinti=3;//正确constintj=5*i;//正确,编译器知道i的值intp=3;constintq=p*4;//错误,不能用变量值来初始化常量2.3数据类型转换所有值类型和引用类型都由一个名为object的基本类发展而来。在C#中还可以通过隐性转换(不会造成数据丢失)或显性转换(可能造成数据丢失或降低精确度)来改变数据类型。2.3.1装箱和拆箱【本节示例参考:\源代码\chapter2\2.3.1\BoxingExample】任何值类型、引用类型可以和object类型之间进行转换。装箱是值类型到object类型或到此值类型所实现的任何接口类型的隐式转换,拆箱是从object类型到值类型或从接口类型到实现该接口的值类型的显式转换。简言之,装箱就是将值类型转换为引用类型;反之,就是拆箱。如代码2-4所示,展示了一个简单的装箱拆箱操作。•代码2-4装箱和拆笨:BoxingExample.cs•1inti=10;•2objectobj=i;//隐式装箱•3objectobj2=(object)i;//显式装箱•4if(objisint)//判断obj是否为int型•5{•6Console.WriteLine(OK);•7}•8Console.WriteLine(obj.GetType());//System.Int322.3.2隐式类型转换只要能保证值不会发生变化,类型转换就可以自动进行。如下面的一段代码:bytex=12;bytey=25;bytem=x+y;//错误intn=x+y;//正确该段代码先声明两个byte类型的数据,然后将这两个byte数据相加到另一个byte类型数据中,这步操作会提示错误,而将byte型数据相加到一个int型数据中,程序运行通过。这是因为,把两个byte值相加,应返回int型结果,而不是另一个byte。因为byte包含的数据只能有8个位的存储空间,即其值的范围只能在0~255之间,所以把两个byte值相加,很容易得到一个不在这个范围里的数据。而用int型的数据来存储两个byte型数据相加的结果范围足够大,不会有数据丢失的危险。在这种情况下,编译器能顺利地通过转换,不用用户指定对数据的转换。2.3.3显式类型转换使用显式类型转换,能够把一种基本数据类型转换成另一种基本数据类型。类型转换时把转换的目标类型名放在转换值之前的小括号里,例如:doublex=12.5d;inti=(int)(x+1);将double型的x加上1转换成int型数据,赋给int型变量i,最后i的结果是13。在转换过程中,小数点后面的所有数据都丢失,损失了精度。读者需要注意,如果对这个double型的数据要进行多次运算,最好先不要进行转换,以免误差累积,造成更大的误差。在上一节的例子中,将byte型的x和y相加,其值会自动转换成int型的,如果用户非要让运算结果还是byte型,这时候也会要用到显式类型转换,如下面代码:bytex=12;bytey=18;bytem=(byte)(x+y);//显式类型转换,将int型的结果转换成byte型第2章C#语法基础(二)教学重点运算符表达式教学内容运算符表达式习题教学过程2.4运算符和表达式C#提供大量运算符,这些运算符指定在表达式中执行哪些操作的符号。例如常见的+、-、*、/、==、!=、、、=、=、binary+、binary-、^、&、|、~、++、--和sizeof()等。此外,很多运算符可被用户重载,以便在应用到用户定义的类型时更改这些运算符的含义。表达式的运算符指示对表达式的数据进行什么样的操作。2.4.1算术运算符C#中的算术运算符主要是对操作数进行基本的数学运算,包含+、-、*、/、%。其中%叫模式运算符,主要作用是给出除法运算的余数,如:7%2=1//表示7除2的余数是1这里要注意运算符+,它除了可以表示进行加法运算外,还可以实现字符串连接运算的功能。这实际上是对运算符的一个重载。例如在前面章节中的示例代码中有这样的代码段:stringc=h;c+=ello;第二行代码等价于:c=c+ello;这里的运算符+实际上已不能叫做算术运算符了,而应该是一个字符串连接运算符,详细内容请参照第3章。2.4.2比较运算符C#中的比较运算符有==、!﹦、、﹦、﹦。C#比较运算符常用于判断某个条件是否成立。例如在前面的代码里有这样的代码段:stringa=hello;stringb=a;Console.WriteLine(a==b);//判断a和b是否相等。其返回结果为true或false在程序设计中,经常会根据某个变量的值来决定程序执行流程,在判断值的取值或取值范围时,就要用到比较运算符。详细内容可以参考第4章程序设计流程章节的知识。2.4.3条件运算符【本节示例参考:\源代码\chapter2\2.4.3\PriorityTest】条件运算符(也叫三元运算符或是三目运算符)是C#里唯一的一个三元运算符。它实际上是if-else结构的简写形式。它可以先判断一个条件,如果条件为真,就返回第一个值,如果条件为假,则返回第二个值。其语法格式如下:条件?值1:值2;假如有这样一个表达式:ab?1:02.4.4赋值运算符赋值运算符的作用,是将某个初始值或是经过运算的值赋给某个变量。C#里的赋值运算符有:=、+=、-=、*=、/=、%=、&=、|=、^=、=、=。除第一项外的其他赋值运算符都是简化的操作符,如x+=y,它等价于x=x+y。这种简化的操作符都需要两个操作数,用于执行算术、逻辑和接位运算,改变第一个操作数的值。2.4.5逻辑运算符逻辑运算符有&、|、!、^、~、&&、||。其中&和|