c#中double未包含balance的未定义与double类型,是为什么?

C#语言基础21 世纪初,微软公司推出了新一代的程序开发环境 Visual Studio.NET,同时也推出了该 环境下的主要编程语言 C#(C Sharp) 。程序设计人员利用.net 平台,配合 C#语言,可以轻 松、快速地开发出实用的 Windows 应用软件,也可以利用 ASP.NET 设计出多姿多彩的动态 网页。本章各节主要包括以下几个方面的内容: ? C#语言程序结构。 ? C#语言数据类型。 ? 类、接口与结构等面向对象的概念。 ? 程序的流程控制。 ? C#语言的主要异常处理语句。1 C#简介C#是微软公司设计用来在.net 平台上开发程序的主要编程语言。 它吸收了 C、 C++与 Java 各自的优点,是一种新型的面向对象的高级程序语言。C#语言主要涉及类(Class) 、对象 (Object) 、继承(Inheritance)等面向对象的概念,在特点上,与 Java 较为相似。1.1 .NET Framework以往的程序设计人员,要么利用 Visual C++的 MFC(Microsoft Foundation Classes) ,要 么通过 Visual Basic APIs (Application Programming Interfaces) 来开发项目, 没有统一的标准, 没有共同的开发结构。为了满足不同项目的开发需求,程序设计人员得不断地学习各种语言 的开发结构,而不能专注于程序本身上的设计。.NET Framework 的出现则改变了这种混乱的 局面,它主要有以下的特点: ? .NET Framework 结合了微软当前所有的开发结构, 让程序设计人员能够利用 C#等中 间语言来编写程序,这类中间语言和其他编程语言的函数库、使用方式、类及名称都 相同。因此,设计人员可以专注于程序算法上的设计,而避免奔波于不同语言的学习。 ? .NET Framework 通过建立一个可以跨不同编程语言的 APIs(Application Programming Interfaces) ,从而能够在不同编程语言间进行连接、错误处理及编程调试(Debug)工 作。通过该平台,程序设计人员可以将开发好的编程,顺利移植到不同的平台上进行 运行,还可以转化成为网络服务等。 ? .NET Framework 以微软的 Component Object Model(COM)作为基础,并且利用更活 动的运算方式将所有组件结合在一起,高效能的网页组件体系简化了编程工作,具有 更好的安全性。 1.2 网页服务时代以往,网站设计人员总要以集成的方式来构建整个网站的应用程序,这种开发方式浪费 了大量的人力物力,而且往往因为其中某一个环节出错,而影响整个项目结构。新一代的网 络编程则可以利用 C#,将 Web 编程创建在例如企业级模板等多层式结构系统上,并利用网 络服务(Web Services)在网上将不同的小组,利用不同开发语言设计出来的模块协同运行。 它降低了开发人员彼此之间沟通的困难。 利用网页服务,程序设计人员将应用程序集成在网络的服务中,远端系统可以通过网络 来调用这些应用程序,就像在本机服务一样。1.3 C#的主要功能C#的主要功能主要表现在以下几个方面: ? 设计 Windows 应用程序 ? 自定义 Windows 控制库 ? 设计控制台应用程序 ? 设计智能设备应用程序 ? 设计 ASP.NET Web 应用程序 ? 设计 ASP.NET Web 服务 ? 设计 ASP.NET 移动 Web 应用程序 ? 自定义 Web 控件库 ASP.NET 正是能 C#为基础所开发出来的控件、标记。在中间语言的领域里,C#是最 具亲和力的一种语言, 它拥有着 C 语言与 Java 语言的主要特点, 同时拥有功能强大的函数库、 方便的模板等,是目前最理想的语言之一。2 C#程序结构程序一般都有其固定的结构与限制。C#撰写出来的应用程序,都是由一个个类(Class) 组成的,连程序也包含在类里。以下是一个用 C#编写的简单的控制台应用程序,它可以形 象地说明 C#编写的应用程序的结构特点。using S namespace ConsoleApplication1 { class Class1 { static void Main(string[] args) { // TODO: 在此处添加代码以启动应用程序 } ?2? C#语言基础 } }上面的程序大致地搭出了应用程序的一个框架,虽然不执行什么操作,但是仍然可以正 确地编译、运行。注意:建议读者从本章开始,对书中所提供的程序示例,亲自进行撰写、编译和运行。在这个过 程中,才可能得到有益的学习经验。2.1 程序入口点几乎所有程序设计语言都有固定的进入方式及程序组成结构,C#也一样。学习过 C 语 言或者 C++,对下面的程序代码便不会感到陌生,它是一个标准的 C 语言程序进入点。void main() { //程序写在这里 }C#程序与 C 语言类似,也是从 Main()函数开始执行,只是需要留意,这里 Main 是 首字母大写,不能写成小写,并且其前面必须加上关键字 static。例如,前面的范例程序中, 程序入口点是:static void Main(string[] args) { // TODO: 在此处添加代码以启动应用程序 } 注意:在 C#语言里,是区分大小写的,所以 Main()完全不等同于 main().2.2 using 的用法在 C#程序中,不管是简单的数据类型,还是执行其他复杂操作,都必须通过函数库才 能实现。.NET 类库(Library)中包含了许多类,例如按钮、复选框等等。利用类库,便可以 开发出具有优美界面的应用程序。 .NET 类库中还包含了许多可以实现其他丰富功能的类,例如存取网络、数据库操作等, 这些类库使 C#编写的程序功能无比强大。 为了方便地运用这些函数库,C#程序中,必须使用 using 关键字将函数库包含进来。如 果有 C 或 C++语言基础,便可以看出,C#的 using 与 C 或 C++中的#Include 十分相似,都 是为了使用已经设计好的程序。 以下程序代码的执行结果是,在 DOS 命令窗口中,按提示键入自己的名字后,显示一 条欢迎信息,如图 1 所示。如果去掉 using 这一行,则程序编译无法通过。?3? 图1 using S namespace ConsoleApplication1 { class Class1 { static void Main(string[] args) {命令窗口中的执行结果Console.WriteLine(&Please enter your name:&); Console.ReadLine(); Console.WriteLine(&Welcome to the world of C# !&); } } }//输出提示信息 //从键盘读入一行字符 //显示欢迎信息范例中使用了 System 下的一个叫做 Console 的类。利用 Console 类,范例程序在 DOS 命令窗口里输出、读入了字符信息。 第一行程序使用 using 关键字的主要目的是让编译器知道,程序中将要使用定义在 System 中的所有类。程序设计人员在程序中,便可以不必通过完整的类的名称来使用类,例 如 System.Console.Write。 如果不使用 using 关键来设计 C#程序,要实现范例中的功能也是可以的,只是这时候 编译器不知道,程序中会使用定义在 System 中的类,设计人员在使用 System 中的类时,需 要输入完整的类名称。例如,上面的范例程序在去掉 using 关键字的第一行程序后,程序要 修改如下:System.Console.WriteLine(&Please enter your name:&); System.Console.ReadLine(); System.Console.WriteLine(&Welcome to the world of C# !&); //输出提示信息 //从键盘读入一行字符 //显示欢迎信息2.3 命名空间(Namespace)C#程序主要是利用命名空间(Namespace)来组织的,函数库就是由一个个的命名空间 来组成。每个命名空间都可以视为一个容器,容器里可以存放类、接口、结构等程序。.NET?4? C#语言基础就是用命名空间来对程序进行分类,把功能相似的类、结构等程序放在同一个命名空间里, 便于管理也便于程序设计人员使用。 最常见也常用的命名空间是 System 命名空间,它包含了许多常用的结构类型,例如 int、 bool,还有许多类,如 Console、Expection。 引用内置命名空间的方法就是使用前一节介绍的 using 关键字:using S程序设计人员还可以设计自己的命名空间,以供别人或者自己设计程序时使用。定义命 名空间,只要在命名空间的名称前加上关键字 namespace 即可,例如:namespace ConsoleApplication1命名空间作为一个容器,其里面的区域需要用一个大括号“ ”来标示,这与类(Class) {} 和方法(Method)的定义一样,例如:namespace MyNamespace { public class HelloWorld { public void Display() { System.Console.WriteLine(&Hello,World!&); } } }这个自定义的命名空间 MyNamespace,包含了一个类 HelloWorld。与使用函数库里的命 名空间一样,程序设计人员可以利用 using 关键字来使用类 HelloWorld,例如:using MyN public class UseClass { static void Main() { HelloWorld.Display(); } } //使用 MyNamespace 里的类 HelloWorld或者不用 using 关键字,而直接用完整的类名来使用类 HelloWorld,例如:MyNamespace.HelloWorld.Display(); //使用 MyNamespace 里的类 HelloWorld2.4 程序区块C#程序语言与 C/C++及 Java 相同,都是以大括号“ ”来区分程序区块的,不论是类 {} (Class) 、方法(Method)还是命名空间(Namespace)都一样,必须将里面的内容以大括号 来囊括。并且每个程序描述语句都必须以分号“; ”作为结尾,例如:public class MyClass ?5? { public static void Main() { System.Console.Write(&C# here&); } } //每一句程序语句都要以分号结尾 //大括号标出 Main 方法的区块来 //大括号标出 MyClass 类的区块来2.5 程序注释程序的注释是帮助阅读程序代码的重要辅助工具。良好的程序注释习惯是优秀的程序员 所必备的品质之一。代码注释不仅不会浪费时间,相反,它会使程序清晰、友好,从而提高 编程效率。 C#的注释方式与 C++一样,每一行中双斜杠“//”后面的内容,以及在分割符“/*”和 “*/”之间的内容都将被编译器忽略。程序设计人员可以利用双斜杠“//”进行单行注释,以 分割符“/*”和“*/”来进行多行注释,例如://源文件 Class1.cs /* 这是我的第一个 C#程序 主要用来输出提示信息 从键盘上读取输入的名字后 再输出欢迎信息 */ //利用 using 关键字,运用 System 命名空间using Snamespace ConsoleApplication1 { class Class1 { //程序入口点 static void Main(string[] args) {//定义自己的命名空间//命名空间里的第一个类Console.WriteLine(&Please enter your name:&); Console.ReadLine(); Console.WriteLine(&Welcome to the world of C# !&); } } }//输出提示信息 //从键盘读入一行字符 //显示欢迎信息注释是用来说明解释程序,提高代码的可读性的,太长的注释反而起不到效果,所以注 释应以简洁为第一要义,避免拖沓冗长。?6? C#语言基础3 C#的数据类型应用程序总是需要处理,而现实世界中的数据类型多种多样。为了让计算机了解需要处 理的是什么样的数据,以及采用哪种方式进行处理,按什么格式来保存数据等等,每一种高 级语言都提供了一组数据类型。不同的语言提供的数据类型不尽相同。3.1 数据类型概述C#内置的数据类型,主要包含了整型、浮点型、字符、布尔型等大部分程序语言都有 的数据类型。表 1 为 C#内置的简单数据类型:表1 数据类型 Sbyte Byte Short ushort Int Uint long Ulong Char Float double Bool decimal 8 bits 8 bits 16 bits 16 bits 32 bits 32 bits 64 bits 64 bits 16 bits 32 bits 64 bits NA 128 bits C#内置简单数据类型 占用内存 数值范围 -128~127 0~255 -32 768~32 767 0~65 535 -21 47 483 648~21 47 483 647 0~4 294 967 295 -9 223 372 036 854 775 808~9 223 372 036 854 775 807 0~18 446 744 073 709 551 615 0~65 535 1.5×10e-45~3.4×10e38 5.0×10e-324~1.7×10e308 Ture 与 False NA在 C#中,所有内置的简单数据类型其实都是一个结构(Structure) ,因此这些数据类型 就拥有所属的成员(Member) ,例如 int 类型包含有 MaxValue、MinValue、ToString 等成员。 以下的程序利用 int 类型的成员“MinValue”取得 int 类型的最小值,并且利用“ToString” 将数值转化为字符串输出。using S public class MemberShow { public static void Main() { int MinNum=int.MinV //定义整型变量,并赋值为整型的 MinValue 成员Console.WriteLine(&Min Value of int is :& + MinNum.ToString()); //将整型转化为字符串 //后输入显示 } }该范例程序运行结果如图 2 所示。?7? 图2结构成员的运用任何编程语言都有属于自已的数据类型,C#除了拥有以上的一般语言都有的简单数据 类型外,主要还有着以下三类的数据类型: ? 值类型(value type) ,包含了变量中的值或数据,即使同为值类型的变量也无法相互 影响。 ? 引用类型 (reference type) 保留了变量中数据的相关信息, , 同为引用类型的两个变量, 可以指向同一个对象,也可以针对同一个变量产生作用,或者被其他同为引用类型的 变量所影响。 ? 指针类型(pointer type) ,在 C#里可以为程序代码加上特殊的标记:unsafe,在程序 里指针,并指向正确的内存位置,其中所用的数据类型就是指针类型了。注意:Java 里并没有指针,C#里却可以、使用指针,但是必须为使用指针的程序块加上 unsafe 程序标记。3.2 值类型(Value type)在 C#语言的领域里,值类型主要包括以下几种数据类型: ? 简单类型(simple type) ? 结构类型(struct type) ? 枚举类型(enums type) ? 默认构造函数(default constructor) 1.简单类型(Simple type) 前一节提到, C#提供了一般语言都拥有的数据类型, 称之为简单数据类型 (simple type) 。 每个简单数据类型都有一个保留字作为其专有的名称,如 int(整数) 、char(字符) 。实际上, 这些以保留字方式定义好的数据类型,都是 System 命名空间里的结构类型(struct type) 。 由于它们比较常用,而且为了减少使用上与其他语言的差异,便采用了简单数据类型的 用法。每个简单数据类型,System 命名空间里都有一个结构类型与之相对应,它们的等价关 系如表 2 所示。表2 简单类型 Sbyte Byte ?8? 简单类型与结构类型的等价关系 对应的结构类型 System.Sbyte System.Byte 描述 8 位整型(signed) 8 位整型(Unsigned) C#语言基础 续表 简单类型 Short ushort Int Uint long Ulong Char Float double Bool decimal 对应的结构类型 System.Int16 System.UInt16 System.Int32 System.UInt32 System.Int64 System.UInt64 System.Char System.Single System.Double System.Boolean System.Decimal 描述 16 位整型(signed) 16 位整型(Unsigned) 32 位整型(signed) 32 位整型(Unsigned) 64 位整型(signed) 64 位整型(Unsigned) Unicode 字符 单精度浮点型 双精度浮点型 布尔型 精度小数(28 位)既然简单数据类型实际上是结构类型,那么它们便具有结构数据类型的特点,有着属于 自己的成员,如变量、常量、方法等。以下的例子主要是运用了整型(int)的常量 MaxValue 及其方法 ToString()。using S public class SimpleTypeMember { public static void Main() { int MaxInt=int.MaxV String myString=MaxInt.ToString(); //定义整型变量,并赋值为 int 的常量成员 //将整型转化为字符串 //输出信息Console.WriteLine(&Max value of Int is:&+myString); } }运行该程序,在 DOS 命令窗口里得到如下的结果:Max value of Int is:简单数据类型具体又可分为以下几类: ? 整数类型 ? 布尔类型 ? 字符类型 ? 实数类型 (1)整数类型 数学上的整数可以从负无穷到正无穷,但是计算机的存储单元是有限的,所以计算机语 言提供的整数类型的值总是一定范围之内的。C#有九种数据类型:短字节型(sbyte) 、字节 型(byte) 、短整型(short) 、无符号短整型(ushort) 、整型(int) 、无符号整型(unit) 、长整 型(long) 、无符号长整型(ulong) 。划分的根据是该类型的变量在内存中所占的位数,各种 类型的数值范围及所占内存空间,可以参照前面的表 2-1 及 2-2。注意:位数的概念是以二进制来定义的,比如说 8 位整数,则表示的数是 2 的 8 次方,为 256。以下的范例可以清楚地看出,当某类型的变量取值大小溢出该类型的数值范围时,计算?9? 机的处理方式:using S public class ValueOut { public static void Main() { int i=; Console.WriteLine(i); i++; Console.WriteLine(i); } } //变量数值加 1,溢出整型的数值范围 //定义变量为整型的最大值程序运行结果为: -上面的范例程序表明,当变量超出数据类型的数值范围时,便会出错。读者不妨把这一 行程序:i++; //变量数值加 1,溢出整型的数值范围改为:i=+2; //变量数值加 2,溢出整型的数值范围再看看程序的运行结果。 (2)布尔类型 布尔类型是用来表示“真”和“假”两个概念的,在 C#里用“true”和“false”来表示。 值得注意的,在 C 和 C++中,用 0 来表示“假” ,用其他任何非 0 值来表示“真” 。但是这种 表达方式在 C#中已经被放弃。在 C#中,true 值不能被其他任何非零值所代替。整数类型 与布尔类型之间不再有任何转换,将整数类型转换成布尔型是不合法的,例如:bool WrongTransform=1; // 错误的表达式,不能将整型转换成布尔型(3)实数类型 数学中的实数不仅包括整数,而且包括小数。小数在 C#中主要采用两种类型来表示: 单精度(float)和双精度(double) 。它们的主要差别在于取值范围和精度不同。程序如果用 大量的双精度类型的话,虽然说数据比较精确,但是将会占用更多的内存,程序的运行速度 会比较慢。 ? 单精度:取值范围在正负 1.5×10e-45 到 3.4×10e38 之间,精度为 7 位数。 ? 双精度:取值范围在正负 5.0×10e-324 到 1.7×10e308 之间,精度为 15 到 16 位。 C#还专门定义了一种十进制类型(decimal) ,主要用于方便在金融和货币方面的计算。 在现代的企业应用程序中,不可避免要涉及到大量的这方面的计算和处理,而十进制类型是 一种高精度、128 位数据类型,它所表示的范围从大约 1.0×10-28 到 7.9×10e28 的 28 到 29 位有效数字。十进制类型的取值范围比 doublc 类型的范围小很多,但它更精确。?10? C#语言基础(4)字符类型(char) 除了数字外,计算机处理的信息还包括字符。字符主要包括数字字符、英文字符、表达 符号等。C#提供的字符类型按照国际上的公认的标准,采用 Unicode 字符集。 可以按下面的方法给一个字符变量赋值:char c=&C&; //给字符变量赋值(5)类型转换 在 C#语言中,一些预定义的数据类型之间存在着预定义的转换。例如,从 short 类型转 换到 int 类型。C#中数据类型的转换可以分为两类:隐式转换(Inplicit conversions)和显式 转换(Explicit conversions) 。 ? 隐式转换,就是系统默认的、不需要加以声明就可以进行的转换。在隐式转换过程中, 编译器无需对转换详细检查就能够安全地执行,转换过程中也不会导致信息丢失,例 如:short st=23; int i= //将短整型隐式转换成整型了? 显式转换,又叫强制类型转换。与隐式转换正好相反,显式转换需要用户明确地指定 转换的类型。显式转换可以发生在表达式的计算过程中,它并不是总能成功,而且常 常引起信息丢失,例如:using S public class TypeConversion { public static void Main() { float f=10.23f; int i=(int)f; Console.WriteLine(f); Console.WriteLine(i); } } //定义一个单精度的实数 //将单精度强制转换为整型 //输出单精度数 //输出整型运行结果如下所示:10.23 10从结果中可以看出,强制转换过程中可能会丢失信息。而且必须显式地说明,说明方法 为在变量前用括号标出要转换成为的数据类型。 2.结构类型(Struct type) 利用简单数据类型,可以进行一些常用的数据运算、文字处理。但是日常生活中,经常 要碰到一些更复杂的数据类型,比如图书馆里每本书的资料,需要书的作者、出版社、书名, 如果按简单类型来管理,那么每本书需要存放到三个不同的变量中,这样工作变得复杂。 C#程序里,定义了一种数据类型,它将一系列相关的变量组织为一个实体,该类型称?11? 之为结构(struct)。定义结构类型的方式如下所示:struct Book {
pub } //结构里,默认为私有(private)成员结构中, 除了包含变量外, 还可以有构造函数 (constructor) 常数 、 (constant) 方法(method) 、 等。下面的范例可以形象地展示结构类型的用法:using S public struct Circle { public const double pi=3.1415926; public Circle(double radius) { r= } public double Area() { return pi*r*r; } public double Circumstance() { return 2*pi*r; } } //计算周长的成员方法 //计算面积的成员方法 //带参数的构造函数 //定义一个成员变量 //定义一个常数public class StructShow { public static void Main() { Circle MyCircle=new Circle(2); //定义了 Circle 结构类型的实例对象Console.WriteLine(&The radius of the circle: &+MyCircle.r); Console.WriteLine(&The area of the circle: &+MyCircle.Area()); Console.WriteLine(&The circumstance of the circle: &+MyCircle.Circumstance()); } }范例程序运行的结果是:The radius of the circle: 2 ?12? C#语言基础 The area of the circle: 12.5663704 The circumstance of the circle: 12.5663704在 C#语言中,可以像 int、bool 或 double 等简单类型一样,通过定义变量的方法来建立 结构类型的实例对象,例如:Circle MyC也可以利用 new 运算符来建立实例,例如范例中的语句:Circle MyCircle=new Circle(2); //定义了 Circle 结构类型的实例对象访问结构类型的内部成员的方法如下所示:MyCircle.r=2; Concole.WriteLine(MyCircle.Area());3.枚举类型(enum) 枚举(enum)实际上是为一组在逻辑上密不可分的整数值提供便于记忆的符号。例如, 定义一个代表星期的枚举类型的变量:enum Week { Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday }; Week ThisW //定义了一个枚举类型的实例变量在形式上,枚举与结构类型非常相似,但是结构是不同的类型数据组成的一个新的数据 类型,结构类型的变量值由各个成员的值组合而成。而枚举类型的变量在某一时刻只能取枚 举中的某一个元素的值。例如,ThisWeek 是枚举类型“Week”的变量,但是它的值要么是 Monday,要么是 Friday 等,在在个时刻只能代表具体的某一天。注意:在枚举中,每个元素之间的相隔符为逗号“, ”这与结构类型不同,结构类型一般是用分号 来分隔各个成员。按照系统的默认,枚举中的每个元素都是 int 型,且第一个元素的值为 0,它后面的每一 个连续的元素的值以 1 递增。或者程序设计人员可以对元素自行赋值。例如,把 Monday 的 值设为 1,则其后的元素的值分别为 2,3??enum Week { Monday=1,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday };为枚举类型的元素所赋的值类型限于 long、int、short 和 byte 等整数类型。3.3 引用类型C#语言中的引用类型(reference type)主要包括以下几种类型: ? 类类型(class type) ? 对象类型(object type)?13? ? ? ? ?字符串类型(string type) 接口类型(interface type) 数组类型(array type) 代表类型(delegate type)1.类类型 类是面向对象编程的基本单位, 是一种包含数据成员、 函数成员和嵌套类型的数据结构。 类的数据成员有常量、域和事件。函数成员包括方法、属性、索引指示器、运算符、构造函 数和析构函数。类和结构同样都包含了自己的成员,有着许多共同特点,但它们最主要的区 别便是:类是引用类型,而结构是值类型。 以下范例程序是一个使用类的典型例子:public class ClassType {
public string Phonenumber { get { } set { phone= } } public ClassType() { } public string GetName() { } ~ClassType() { } } //类的析构函数 //类的成员方法 //类的构造函数 //定义属性变量的另一种方法 //定义了成员变量类还支持继承机制。通过继承,派生类可以扩展基类的数据成员和函数方法,进而达到 代码重用和设计重用的目的。有关类的概念将在本章 2.4 小节中有详细讲解。?14? C#语言基础2.对象类型 对象类型(object type)是所有其它类型的基类,C#中的所有类型都直接或间接从对象 类型中继承。因此,对一个对象类型的变量,可以赋予任何类型的值,例如:int x=1; object obj1; obj1=x; object obj2=&B&; //赋予对象类型变量为整型的数值 //赋予对象类型变量为字符值对对象类型的变量声明, 采用 object 关键字, 这个关键字是在.NET 框架结构中提供的预 定义的命名空间 System 中定义的,是类 System.Object 的别名。 3.数组类型 数组(array)是一种包含了多个变量的数据类型,这些变量称为数组的元素(element) 。 同一个数组里的数组元素必须都有着相同的数据类型,并且利用索引(index)可以存取数组 元素。 C#定义数组的方式与 C/C++或 Java 一样,必须指定数组的数据类型,例如:int[] IntA但是,经过定义的数组并不会实际建立数组的实体,必须利用“new”运算符才能真正 建立数组,例如:IntArray=new int[4];建立对象时,数组的长度定义必须使用常数,不能使用变量,否则会发生错误,例如:int i=3; int[] ArrayTest=new int[3]; int[] ArrayTest2=new int[i]; //长度定义为常数,正确 //长度定义为变量,错误经过 new 关键字建立的数组,如果没有初始化,则其元素都会使用 C#的默认值,例如 int 类型的默认值为 0、bool 类型为 false 等。如果想自行初始化数组元素,可以用以下的方式 来编写:int[] ArrayTest=new int[3]{8,16,32}; // 初始化数组已经建立的数组可以利用索引来存取数组元素。 要注意的是, C#数组的索引值是从 “0” 开始的,也就是说,上面的含有 3 个元素的 ArrayTest 数组,3 个元素存取方式分别为: ArrayTest[0]、ArrayTest[1]、ArrayTest[2]。 下面的范例大致展示了一维数组的定义、初始化及元素存取等用法:using S public class ArrayTest1 { public static void Main() { int[] arr=new int[4]; for(int i=0;i&arr.Li++) arr[i]=i; //对数组的每一个元素进行赋值 ?15? //定义数组,并利用 new 建立数组 for(int i=0;i&arr.Li++)//输出显示每一个元素的值Console.WriteLine(&arr[&+i+&]'s value is &+i); } }在 C#语言中,除了可以定义一维数组外,还可以定义使用多维数组。定义规则的多维 数组时,可以采用如下的方式:int[,] MulArray=new int[3,5];也可以直接初始化多维数组,如下所示:int[,] MulArray=new int[,]{ {1,2,3},{4,5,6}};仔细观察上面的初始方式,可以看出,如果要初始化三维数组,只需要在一个大括号里, 放几个二维数组作为三维数组的元素,元素用逗号隔开,如下所示:int[,,] ThreeDim=new int[,,]{ {{1,2,3},{4,5,6}}, {{3,2,1},{6,5,4}} };C#还有一种由多个数组组成的数组模式, 称为 “锯齿型数组 (jagged)。 ” 这类型的数组, 是由多个数组组成,这些数组的维数,元素个数可以不尽相同。例如:int[][] JaggedArray=new int[3]; JaggedArray[0]=new int[]{1,2,3}; JaggedArray[1]=new int[]{1,2,3,4}; //定义了一个锯齿数组,数组里有三个元素 //数组的第一个元素被初始化为有三个元素的数组 //数组的第二个元素被初始化为有四个元素的数组JaggedArray[2]=new int[]{1,2,3,4,5}; //数组的第三个元素被初始化为有五个元素的数组上面程序代码所生成的二维数组,其在形式上可以用图表形象表示,见图 2-3。图 2-3锯齿数组结构下面的程序显示了多维数组的定义方法:int[][] arr1=new int[2][]{new int[]{1,2}, new int[]{1,2,3,4,5}}; //二维锯齿数组 int[][,] arr2=new int[3][,]; int[][,,][,] arr3=new int[5][,,][,]; //三维数组 //六维数组第 2 个数组是以二维数组作为其数组元素,第 3 个数组是由以二维数组作为元素的三维 数组所组成的一维数组。 Array 类中有几个常用的成员,例如 Length 属性会返回数组的长度;Rank 属性会返回数 组的维数,Clear 方法可以将所有的数组元素设置 C#的默认值。程序示例如下:int[] arr=new int[5]; System.Console.WriteLine(arr.Length);运行后,输出显示数组的长度为:5。?16? C#语言基础4.字符串类型 C#还定义了一个基本的类 string,专门用于对字符串的操作。这个类也是在.NET 框架 结构的命名空间 System 中定义的,是类 System.String 的别名。 字符串不仅是一种数据类型,一种类别,它还可以视为一个数组,一个由字符组成的数 组。字符串的数组用法如下所示:using S public class StringShow { public static void Main() { string MyString=&Welcome!&; Console.WriteLine(MyString[0]); Console.WriteLine(MyString[4]); } } //读取字符串的第一个字符 //读取字符串的第五个字符程序中将字符串 MyString 看作为一个字符数组,并通过索引来读取数组元素。注意:字符串的索引方式只能读取,却不允许写入,除非整个字符串都一并修改才行。利用运算符“+”可以将两个字符串合成一个字符串,例如:string MyString1=&Welcome&; string MyString2=&,everyone!&; string MyString3=MyString1+MyString2; Console.WriteLine(MyString3);在 C++中或者 Java 中,若字符串包含了一些特殊字符,如“\”和“”” ,必须在字符前 加上反斜杠“\” 。这种方式使字符串变得不容易阅读,例如:string MyString=&D:\\Eidy\\Book\\HappyEveryday.txt&;为了避免字符串变得不易辨识,C#提供了一个专门的运算符“@” ,它可以去除字符串 中不必要的反斜杠,例如:string MyString=@&D:\Eidy\Book\HappyEveryday.txt&;“@”的优点就是忽略不需要处理的字符串,也就是说,将“@”运算符后,双引号内 的字符串视为单纯的字符串,不管有没有包含特殊字符。再比如,要输出“Hello”这样一个 带双引号的字符串,则程序代码如下:string MyString5=@&&&Hello&&&; Console.WriteLine(MyString5);3.4 变量变量是程序语言中最基础的组成部分,它可以被定义为不同的数据类型,也可以给予不 同的数值。变量被定义后,在执行阶段,会一直存储在内存中。变量的值可根据指定运算符?17? 或增、或减来改变。 C#语言中,主要定义了几种类型的变量: ? 静态变量(static variable) ? 非静态变量(instance variable) ? 数组元素(array element) ? 局部变量(local variable) ? 值参数(value parameters) ? 引用参数(reference parameters) ? 输出参数(output parameters) 1.静态变量 带有“static”修饰符声明的变量称为静态变量,一量静态变量所属的类被装载,直到包 含该类的程序运行结束时,它将一直存在。静态变量的初始值就是该变量类型的默认值。 静态变量与静态方法一样,不需要建立其所属类的对象,便可直接存取这个变量,例如:using S public class VariableInclude { public static string name=&AndyLau&; public static int age=40; public string country=&china-Honkong&; } public class VariableUse { public static void Main() { Console.WriteLine(VariableInclude.name); Console.WriteLine(VariableInclude.age); // Consloe.WriteLine(VariableInclude.country); VariableInclude vi1=new VariableInclude(); Console.WriteLine(vi1.country); } } 非静态变量不能直接调用,否则会出错 //定义类的对象后,才能调用非静态变量 // //静态变量不用定义实例对象,可以直接调用 //定义了静态字符串变量 //定义了静态整型变量 //定义非静态变量程序中可以看出,不用定义类的实例对象便可以直接存取静态变量 name、age,但是非 静态变量不能直接存取,否则会出错。非静态变量只有建立对象后,才能存取。 2.非静态变量 不带有“static”修饰符声明的变量便称为非静态变量。由前面静态变量小节里的程序范 例可以知道,非静态变量一定要在建立变量所属类型的对象后,才开始存在于内存里。如果 变量被定义在类中,那么当对象被建立时,变量随之诞生;对象消失,变量也随之消失。如 果变量定义在结构里,那么结构存在多久,变量也存在多久。?18? C#语言基础3.数组元素 元素是构成整个数组的基本单位,每一个元素相当于一个变量,数组便是由许多数据类 型相同的变量所组成的集合。其中的每个数组元素都可以变量视之,进行存取数据,例如:int[] arr=new int[3]; arr[0]=1;4.局部变量 局部变量是指在一个独立的程序块,如一个 for 语句、switch 语句或者在方法里声明的 变量,它只在该范围中有效。当程序运行到这一范围时,该变量开始生效,程序离开时,变 量就失效了,例如:for(int i=1;i&9;i++) { Console.WriteLine(i); } Console.WriteLine(i); //错误的代码,因为此时局部变量 i 已经失效了 //正确的代码,因为此时还在有效范围内与其他几种变量类型不同的是,局部变量不会自动被初始化,所以也就不存在默认值, 必须被赋值后才能使用。4 类(class)类是面向对象的程序设计的基本构成模块。从定义上讲,类是一种数据结构,但是这种 数据结构可能包含数据成员、 函数成员以及其它的嵌套类型。 其中数据成员类型主要有常量、 域;函数成员类型有方法、属性、构造函数和析构函数等。4.1 类的声明C#虽然有许多系统自定义好的命名空间及类供程序设计人员使用,但是,设计人员仍 然需要针对特定问题的特定逻辑来定义自己的类。 设计人员定义类主要包括定义类头和类体两部分,其中类体又由属性(域)与方法组成, 下面的程序片断定义了一个典型的类DD电话卡。public class PhoneCard { public long CardN private int password=; public bool PerformConnection(int pw) { //定义的公有方法,开始拨号 ?19? //定义有公有的成员卡号 //定义了么有的成员密码 if(pw==password) { connected = } else { connected = } } void PerformDial() { if(connected) balance-=0.5; } } //定义的方法,扣除余额程序范例中定义了一个自定义类 PhoneCard。类头使用关键字 class 标志类定义的开始, 后面跟着类名称。类体用一对大括号括起,包括域和方法。4.2 类的成员类的成员主要有以下类型: ? 成员常量,代表与类相关联的常量值。 ? 域,即类中的变量 ? 成员方法,复杂执行类中的数据处理和其他操作。 ? 属性,用于定义类中的值,并对它们进行读写。 ? 构造函数和析构函数,分别用于对类的实例进行初始化和销毁。 1.成员访问控制符 在编写程序时,可以对类的成员使用不同的访问修饰符,从而定义它们的访问级别 ? 公有成员(public) 。C#中的公有成员提供了类的外部界面,允许类的使用者从外部 进行访问,公有成员的修饰符是“public” 。这是对成员访问限制最少的一种方式。 ? 私有成员(private) 。C#中的私有成员仅限于类中的成员可以访问,从类外部访问私 有成员是不合法的。如果在声明中,没有出现成员的访问修饰符,按照默认方式成员 为私有。私有成员的修饰符为“private” 。 ? 保护成员(protected) 。为了方便派生类的访问,又希望成员对于外部隐藏,可以使用 “protected”修饰符,声明成员为保护成员。 ? 内部成员(internal) 。使用“internal”修饰符类的成员是一种特殊成员。这种成员对 于同一包中的应用程序或库是透明的。而在包.NET 之外是禁止访问的。?20? C#语言基础下面的例子详细地说明了类的成员访问修饰符的用法:using S class Book { pr priv public void func() { number=5; price=22.0; publisher=&Tsinghua Publisher&; } } class EnglishBook { p public void func() { author=&AndyLau&; Book book1=new Book(); book1.number=6; //正确,可以访问自己的变量 //定义了 Book 的实例对象 //正确,可以访问类的公有变量 //错误,不能访问类的私有变量 //正确,可以访问自已的公有变量 //正确,可以访问自己的保护变量 //正确,可以访问自己的私有变量 //定义了公有变量,数量 //定义了保护变量,价格 //定义了私有变量,出版社book1.publisher=&Peking University Publisher&; book1.price=25.0; } } class ComputerBook:Book { public void funct() { Book b=new Book(); b.number=8; b.publisher=&People Publisher&; price=25.0; } }//错误,不能访问类的保护变量//电脑书籍继承了 Book 类//正确,可以访问类的公有变量 //错误,不可以访问其私有变量 //正确,可以访问类的保护变量?21? 2.域与属性 (1)域 域是类和对象的属性,它可以是基本数据类型的变量,也可以是其他类的对象。若将类 中的某个域声明为 static,那该域称为静态域,否则为非静态域。一般来说,静态成员是属于 类所有的,非静态成员则属于类的实例DD对象。 以下示例详细介绍了如何使用静态域与非静态域。public class Book { public static string publisher=&三联书社&; public void func1() { publisher=&Hello Publisher&; number=5; } static void func2() { publisher=&Hello Everybody&; number=7; } } class Test { public static void Main() { Book b=new Book(); b.number=6; b.publisher=&商务书局&; Book.number=7; Book.publisher=&源源书社&; } } //定义了类的实例对象 //正确,对象可以访问其非静态变量 //错误,对象不可以访问静态变量 //错误,类不可以直接访问其非静态变量 //正确,类可以不建立对象而直接访问静态变量 //正确,可以访问本类的静态变量 //错误,静态方法只能访问本类静态变量 //定义了静态方法 //正确,访问本类的静态变量 //正确,可以访问本类的非静态变量 //定义了静态变量 //定义了非静态变量类的非静态变量成员属于类的实例所有,每创建一个类的实例对象,都在内存中为非静 态成员开辟了一块存储区域。有多少个实例对象,就有多少个属于每个对象的非静态变量存 储空间。而类的静态成员属于类所有,为这个类的所有实例所共享,无论这个类创建了多少 个对象,一个静态成员在内存中只占有一块存储区域。 (2)属性 C#中的属性充分体现了对象的封装性:不直接操作类的数据内容,而是通过访问器进 行访问。它借助于 get 和 set 对属性的值进行读写。?22? C#语言基础在属性的访问声明中,主要有三种方式: ? 只有 set 访问器,表明属性的值只能进行设置而不能读出。 ? 只有 get 访问器,表明属性的值是只读的,不能改写。 ? 同时具有 set 访问器和 get 访问器,表明属性的值的读写都是允许的。 每个访问器的执行体中,所有属性的 get 访问器都通过 return 来读取属性值,set 访问器 都通过 value 来设置属性的值。 举个例子,一个学生的高考分数档案资料中,有学生的考号、姓名、分数、录取学校。 考号一经确定后不能再改,所以只能读,不能写;姓名也是只读的;分数与录取学校都是可 读写的,程序设计如下:public class StudentData { priva public int StudentNo { get { } } public string Name { get { } } public int Grade { get { } set { grade= } } ?23? //可读写属性 //只读属性 //只读属性 public string University { get { } set { university= } } } //可读写属性读写属性与一般的成员变量一样,例如:StudentData sst=new StudentData(); sst.University=&Tsinghua University&; Console.WriteLine(sst.Name); 注意:属性在定义的时候,要注意属性的名称后面不能加上括号,否则变成方法了。3.构造函数 构造函数是用于执行类的实例的初始化。每个类都有构造函数,即使没有声明它,编译 器也会自动提供一个默认的构造函数。在访问一个类的时候,系统将最先执行构造函数中的 语句。默认的构造函数一般不执行什么操作,例如:public class Class1 { public Class1() { } } //系统默认的构造函数使用构造函数应该注意以下几个问题: ? 一个类的构造函数要与类名相同。 ? 构造函数不能声明返回类型。 ? 一般构造函数总是 public 类型,才能在实例化时调用。如果是 private 类型的,表明类 不能被实例化,这通常只用于只含有静态成员的类。 ? 在构造函数中,除了对类进行实例化外,一般不能有其他操作。对于构造函数也不能 显式地来调用。 构造函数可以是不带参数的,这样对类的实例的初始化是固定的,就像默认的构造函数 一样。有时候,在对类进行初始化时,需要传递一定的数据,以便对其中的各种数据进行初 始化,这时可以使用带参数的构造函数,实现对类的不同实例的不同初始化。 以下的程序范例形象地展示了构造函数的定义及使用方法:using S ?24? C#语言基础 public class MyClass { public MyClass() { x=1;y=2; } public MyClass(int val) { x=y=val+1; } public MyClass(int val_x,int val_y) { x=val_x;y=val_y; } } public class ClassTest { public static void Main() { MyClass myClass1=new MyClass(); MyClass myClass2=new MyClass(3); MyClass myClass3=new MyClass(5,6); //用不带参数的构造函数来实例化 //用带一个参数的构造函数来实例化 //用带有两个参数的构造函数来实例化 &+myClass1.y); &+myClass2.y); &+myClass3.y); //带有两个参数的构造函数 //带有一个参数的构造函数 //不带参数的自定义构造函数Console.WriteLine(&The x and y of myClass1 is:&+myClass1.x+& Console.WriteLine(&The x and y of myClass1 is:&+myClass2.x+& Console.WriteLine(&The x and y of myClass1 is:&+myClass3.x+& } }程序运行结果为:The x and y of myClass1 is:1 The x and y of myClass1 is:3 The x and y of myClass1 is:5 2 4 6范例程序中定义了三个构造函数,每个函数的入口参数都不一样,在实例化时,可以根 据需要选择相应的构造函数。实际上,在实例化时,构造函数的名称还都是一样,只是入口 参数不一样而已,这是方法(method)中的重载功能,具体见下一节的有关介绍。 4.析构函数 在类的实例超出范围时,为确保它所占的存储空间能被收回,C#中提供了析构函数, 用于专门释放被占用的系统资源。?25? 析构函数的名字与类名相同,只是在前面加了一个符号“~” ,析构函数不接受任何参数, 也不返回任何值,例如:public class Class1 { ~Class1() { } } 注意:析构函数不能返回值,也不能显式调用,否则会出现错误。 //析构函数4.3 方法(method)在面向对象的程序语言设计中,对类的数据成员的操作都封装在类的成员方法中。方法 的主要功能便是数据操作。 方法的声明包括修饰符、返回值数据类型、方法名、入口参数和方法体。一般的方法的 声明格式如下所示:public int SumOfValue(int x,int y) { return x+y; }方法中的修饰符是用来指定方法的访问级别和使用方法的,主要的方法修饰符有: ? new ? public ? protected ? internal ? private ? static ? virtual ? sealed ? override ? abstract ? extern 方法的返回值类型必须是合法 C#的数据类型,并且在方法体里,用“return”得到返回 值。如果没有返回值,则声明时,用关键字“void” ,并且方法体里中不使用“return”来返回 数值。例如:public string returnString() { ?? Return ?? ; ?26? //用 return 返回数值 C#语言基础 } public void NoReturn() { ?? } //没有 return 返回值1.静态与非静态方法 C#的类定义的方法有两种:静态和非静态。使用了 static 修饰符的方法为静态方法,否 则为非静态。 静态方法是一种特殊的成员方法,像静态变量一样,它不属于类的某一个具体的实例。 非静态方法可以访问类中的任何成员,而静态方法只能访问类的静态成员,例如:public class StaticMethod { static void myMethod() { x=1; y=2; } } //错误,不能访问非静态变量 //正确,可以访问静态变量2.方法的重载 在前面介绍构造函数的例子中,我们已经看到了构造函数重载的用法。实际上,类的成 员方法的重载也是类似的。在类里,有两个以上的方法名字相同,只是使用的参数类型或者 参数个数不同,就叫做方法的重载。 使用重载的目的是为了用一个方法的名称,即可实现对不同的数据类型进行的大致相同 的操作。例如,两个实数的求和操作,实数类型有可能是整型,也有可能是浮点型。如果不 利用重载功能,那么得定义两个函数对整型和浮点型分别求和,程序如下所示:public class myApp { public int AddInt(int x,int y) { return x+y; } public double AddDouble(double x,double y) { return x+y; } } ?27? //对两个浮点型求和 //对两个整型求和 public class AddTest { public static void Main() { myApp cla=new myApp(); int x=cla.AddInt(12,24); double y=cla.AddDouble(34.56,56,43); } } //调用整型求和方法 //调用浮点型求和方法在 C#中,利用重载功能,可以给两个求和的方法取同一个名字,那么在调用方法时, 只需使用这个方法名,编译器会自动根据入口参数的数据类型来决定调用整型求和,还是浮 点型求和方法。范例程序如下:public class myApp { public int AddMethod(int x,int y) { return x+y; } public double AddMethod(double x,double y) { return x+y; } } //对两个浮点型求和 //使用同样的方法名 //对两个整型求和public class AddTest { public static void Main() { myApp cla=new myApp(); int x=cla.AddMethod(12,24); double y=cla.AddMethod(34.56,56,43); } } //调用求和方法,编译器会自动调用整型求和 //调用求和方法,编译器会自动调用浮点型求和4.4 继承为了提高软件模块的可移植性和可扩充性,以便提高软件的开发效率,程序设计人员总 是希望能够利用已有的开发成果,同时又希望在开发过程中能够有足够的灵活性,不仅仅拘 泥于模块的利用。面向对象的程序设计语言为实现此功能,提供了两个重要的特性:继承性 (inheritance)和多态性(polymorphism) 。?28? C#语言基础在现实世界中,许多实体之间并不是相互孤立的,它们往往具有共同的特征,但同时也 存在着差别。为了体现这种相似与不相似,可以用层次结构来描述。以电话卡为例,如图 4 所示。图4电话卡层次结构图图 2-4 反映了电话卡的派生关系。最高层的实体具有最一般最普遍的特征,越下层的事 物越具体,并且下层包含了上层的特征。为了用软件语言对现实世界中的诸如此类的层次结 构进行模型化, 面向对象的程序设计语言引入了继承的概念。 一个类从另一个类派生出来时, 派生类从基类那里继承特性。派生类可以作为基类再派生出子类,一层层下去,形成层次结 构。注意:在 C#中,派生类只能从一个类中继承,而不能像 C++那样,可以从多个基类中派生一个 类出来。派生类从它的基类中继承成员:方法、域、属性等。除了构造函数和析构函数外,派生 类隐式地继承了基类的所有成员。 下面的程序范例是电话卡与 201 卡之间的继承关系,仔细地学习可以获得一些感性的认 识。using S public class PhoneCard { public int CardN p public PhoneCard(int cardNumber) { CardNumber=cardN connected= } public void WriteCardNo() { Console.WriteLine(CardNumber); ?29? //成员方法 //初始化卡号 //初始化连接状态 //构造函数初始化 } } public class Card201:PhoneCard { public Card201(int pw,int cno):base(cno) { CardNumber= connected= password= } } public class CardTest { public static void Main() { Card201 card=new Card201(5252); card.WriteCardNo(); } } //使用构造方法实例化 //201 卡继承了基类的成员方法,调用之 //继承了基类的卡号变量 //继承了基类的已连接变量 //自己的变量 //201 卡特有的特征:密码 //构造方法Card201 类继承了 PhoneCard 类的方法与属性,并且定义了自己的成员变量:password。 C#中的继承符合下列规则: ? 继承是可传递性的,也就说如果 B 继承了 A,而 C 继承了 B,则 C 不仅继承了 B 的 成员,而且继承了 A 的成员。 ? 派生类是对原有基类的扩展,它可以添加新的成员,但是不能除去已经继承的成员。 ? 构造函数与析构函数不能继承。 在继承的过程中,往往还涉及两个概念 ? 覆盖 ? base 关键字。 1.覆盖(hide) 在派生类的成员声明中,可以声明与继承而来的成员同名的成员,这时称派生类的成员 覆盖(hide)了基类的成员。在覆盖的情况下,编译不会报告错误,但会给警告,对派生类 的成员使用 new 关键字,可以关闭该警告。 以前面电话卡的程序范例来说明,电话卡类 PhoneCard 中已经定义了一个成员方法 WriteCardNo() ,可以在 201 电话卡中也定义一个 WriteCardNo 方法() ,覆盖原有的方法, 代码如下:public class Card201:PhoneCard { ?? ?30? C#语言基础 new public void WriteCardNo() { Console.WriteLine(&The number of the card is:&); } }2.base 关键字 Base 关键字主要是为派生类调用基类成员提供一个简写的方法, 当基类中的方法没有被 继承,如构造函数,或者是无法直接调用,可以使用 base 关键字。先看看一个程序代码:using S public class PhoneCard { public int CardN public void InitCard() { CardNumber=123456; } } public class Card201:PhoneCard { new public void InitCard() { base.WriteCardNo(); password=654321; } } // 调用基类的方法类 Card201 继承了 PhoneCard,所以也继承了它的成员,包括 InitCard()方法。但是,该 方法在派生类中被覆盖了,为了调用基类的 InitCard 方法,程序中采取了 base 关键字。5 流程控制在程序设计过程中,有时为了需要,经常要转移或者改变程序的执行顺序,达到这目的 的语句叫作流程控制语句。在程序模块中,C#可以通过条件语句控制程序的流程,从而形 成程序的分支和循环。主要的流程控制关键字有: ? 选择控制:if、else、switch、case ? 循环控制:while、do、for、foreach ? 跳转语句:break、continue?31? 5.1 选择在 C#领域里,要根据条件来做流程选择控制时,可以利用 if 或 switch 这两种命令。这 两种命令与 C 语言中的用法一样。 1.If 语句 If 语句是最常用的选择语句,它根据布尔表达式的值来判断是否执行后面的内嵌语句。 其格式一般如下:if(布尔表达式) { //表达式; } else { //表达式 }当布尔表达式的值为真时, 则执行 if 后面的表达语句; 如果为假, 则继续执行下面语句, 如果还有 else 语句,则执行 else 后面的内嵌语句,否则继续执行下一条语句。下面的例子是 根据 x 的符号来决定 y 的数值的范例程序:if(x&=0) { y=1; } else { y=-1; }如果 if 或 else 之后的大括号内的表达语句只有一条执行语句,则嵌套部分的大括号可以 省略。如果包含了两条以上的执行语句,则一定要加上大括号。 如果程序的逻辑判断关系比较复杂,则可以采用条件判断嵌套语句。If 语句可以嵌套使 用,在判断中,再进行判断。具体形式如下:if(布尔表达式) { if(布尔表达式) {??} else {??} } else { ?32? C#语言基础 if(布尔表达式) {??} else {??} } 注意:每一条 else 与离它最近且没有其他 else 与之对应的 if 相搭配。2.Switch 语句 If 语句每次判断后,只能实现两条分支,如果要实现多种选择的功能,可以采用 switch 语句。Switch 语句根据一个控制表达式的值,来选择一个内嵌语句分支来执行。它的一般格 式为:switch(控制表达式) { case ??: case ??: default ?? }Switch 语句在使用过程中,需要注意下列几点: ? 控制表达式的数据类型可以是 sbyte、byte、short、ushort、unit、long、ulong、char、 string 或者枚举类型。 ? 每个 case 标签中常量表达式必须属于或能隐式转换成控制类型。 ? 每个 case 标签中的常量表达式不能相同,否则编译会出错。 ? Switch 语句中最多只能有一个 default 标签。 举个例子,国内学分是以百分制,国外大学则是四分制。出国的学生在换算分数时,按 照的算法是:90 分以上换算为 4 分,80 到 90 为 3 分,70 到 80 为 2 分,60 到 70 为 1 分,60 以下 0 分计算。这种换算方法如果用 switch 语句来实现,其流程图如图 5 所示。图5流程图 ?33? 程序代码如下所示:int x,y; x=(int)(x/10); switch(x) { case 10:y=4; case 9:y=4; case 8:y=3; case 7:y=2; case 6:y=1; default :y=0; } //有且只有一个 default 语句, //各个 case 标签表达式值不能相同 //先算出分数的十位数 //判断十位数的大小在 C#中使用 switch 语句, 还需要注意, 虽然 C/C++允许 case 标签后不出现 break 语句, 但是 C#不允许这样。它要求每个标签项后面使用 break 语句,或者跳转语句,而不能从一 个 case 自动遍历到其它 case,否则编译错误。 例如,C/C++语言中,可能出现如下的程序代码:case 7:y=2; case 6:y=1; default :y=0;这样的程序代码在 C#中是不允许的。在 C#中,如果想实现类似 C/C++中的自动遍历 的功能,可以用跳转语句 goto 来实现,上面的程序代码改写为:case 7:y=2;goto case 8; case 6:y=1; default :y=0;在 C#中,能够避免产生“遍历” ,还有 return 语句,例如:switch(x) { case 10:y=4; case 7:y=2;goto case 8; case 6:y=1; } //采用 return,不会遍历到下一个 case,正确5.2 循环循环语句可以实现一个程序模块的重复执行,这对于简化程序,组织算法有着重要的意 义。C#总共提供了四种循环语句: ? for 语句 ? do-while 语句 ? while 语句 ? foreach 语句?34? C#语言基础1.for 语句 C#中 for 循环的用法与 C 语言里相同,其中必须给出三个参数,作为控制循环的起点、 条件、累计方式,一般格式为:for(起点;条件;累计方式) { //for 循环语句 }具体的使用方式,可以见以下的例子:for(int i=0;i&5;i++) { Console.Write (i); }该代码输入的结果便是 01234,当变量 i 等于 5 时,不满足条件,跳出循环。 for 语句还可以嵌套使用,以完成大量重复性、规律性的工作。举个例子,在数学上,经 常要把一列数进行排序,该排序过程就可以用 for 语句的嵌套来实现:int[] a=new int[5]{9,8,5,3,6}; for(int i=0;i&a.Li++) { for(int j=i+1;j&a.Lj++) { if(a[j]&a[i]) { temp=a[i]; a[i]=a[j]; a[j]= } } } for(int i=0;i&a.Li++) Console.Write(a[i]); //输出所有的元素 //结果是最小的数值都一个个被排到前面来 //如果比 a[i]小,则交换两数值 //从 i 后面的每个元素扫描程序的运行结果是:35689,实现了从小到大的排序功能。 2.do 与 while 语句 do 与 while 的使用方式与 for 有点相同, 不过 for 循环必须给定起点, 终点, do 与 while 而 只限定条件,只有满足条件才执行内嵌表达式,否则离开循环,继续执行后面的语句。先以 一个例子来介绍:int x=0; int[] a=new int[3]{166,173,171}; ?35? while(x&a.Length) { if(a[x]==171) Console.WriteLine(x); x++; }//条件判断 //找出 171 的位置并输出//累讲条件判断的变量do-while 语句与 while 语句不同的是,它将内嵌语句执行一次,再进行条件判断是否循 环执行内嵌语句,上面的例子用 do-while 来实现的话,程序代码如下所示:int x=0; int[] a=new int[3]{166,173,171}; do { if(a[x]==171) Console.WriteLine(x); x++; } while(x&a.Length) ; //条件判断 //累讲条件判断的变量 //找出 171 的位置并输出3.foreach 语句 foreach 语句可以让设计人员扫描整个数组的元素索引。它不用给予数组的元素个数,便 能直接将数组里的所有元素输出。请看下面这个例子:int[] a=new int[5]{23,34,45,56,67}; foreach(int i in a) { Console.WriteLine(i); }使用 foreach 语句时,并不需要数组里有多少个元素,通过“in 数组名称”的方式,便 会将数组里的元素值逐一赋予变量 i,之后再输出。foreach 语句一般在不确定数组的元素个 数时使用。5.3 跳跃程序设计里,为了让程序拥有更大的灵活性,通常都会加上中断或跳转等程序控制。C #语言中可能用来实现跳跃功能的命令主要有: ? break 语句 ? continue 语句 ? goto 语句 1.break 语句 在前面介绍 switch 语句的章节里,已经使用过 break 命令。事实上,break 不仅可以使用?36? C#语言基础在 switch 判断语句里,还可以在程序的任何阶段上运用。它的作用是当前的循环,例如:int[] a=new int[3]{1,3,5}; for(int i=1;i&a.Li++) { if(a[i]==3) a[i]++; } //当 a[i]=3 时,跳转到此程序中当满足 a[i]=3 时,运行 break 命令,程序就跳出当前的 for 循环。 2.continue 语句 continue 语句会让程序跳过下面的语句,重新回到循环起点,例如:for(int i=1;i&10;i++) { if(i%2==0) Console.Write (i); } //跳转至此如果变量 i 为偶数,则不执行后面的输出表达式,而是直接跳回起点,重新加 1 后继续 执行。程序输出结果为:13579。 3.goto 语句 与 C 语言一样,C#也提供了一个 goto 命令,只要给予一个标记,它可以将程序跳转到 标记所在的位置,例如:for(int i=1;i&10;i++) { if(i%2==0) goto OutL Console.WriteLine(i); } OutLabel: //跳转至此Console.WriteLine(&Here,out now!&);6 异常处理在编写程序时,不仅要关心程序的正常操作,还要把握现实世界中可能发生的各类难以 预期的情况。例如数据库无法连接,网络资源不可用等等。C#语言中提供了一套安全有效 的异常处理方法,用来解决这类现实问题。?37? 6.1 溢出的处理利用计算机进行数学计算时,因为数据类型是有数值范围的,所以计算结果往往可能超 出这个范围,这种情况称之为“溢出” 。 默认的情况下,对于溢出是不进行控制的,例如下列的情况:using S public class OverFlowExample { public static void Main() { int x=int.MaxV int y=int.MaxV int z=x+y; //定义 x 为整型的最大数值 //定义 y 为整型的最大数值 //两变量相加,结果会产生溢出Console.WriteLine(&The default of the overflow is:&+z); } }程序运行结果,如图 6 所示。图6默认情况下的相加结果从输出结果可以看出,默认情况下,对于溢出是不进行处理的。这样程序运行的结果就 会不正确,对整个程序是相当不利的,因为结果并不是设计人员所预料的那样,而是产生了 溢出,有可能危及整个程序的运行。 为了防范溢出的情况发生,C#提供了一个关键词 checked,帮助设计人员检查运算是否 发溢出。如果发生溢出,则抛出一个异常,例如:public static void Main() { int x=int.MaxV int y=int.MaxV int z=checked(x+y); //定义 x 为整型的最大数值 //定义 y 为整型的最大数值 //两变量相加,结果会产生溢出,利用 checked 来处理Console.WriteLine(&The default of the overflow is:&+z); }程序运行的结果如图 7 所示。?38? C#语言基础图7控制的溢出会抛出一个异常加上 checked 后,执行结果出现了异常信息。与 checked 相反的是,如果使用 unchecked 关键词,则不检查是否发生溢出,继续执行程序,这是 C#默认的运算式检查状态。6.2 异常的处理在 C#中,所有的异常都是 System.Expection 这个类的派生类的实例。C#中获取例外的 方式与 Java 一样,都是利用 try、catch 和 throw 这三个关键词来获取、处理或抛出异常的。 例如,当程序中如果有除以 0 的操作,则会抛出一个 DivideByZeroException 的异常。using S public class ExpectionExmaple { public static void Main() { int x=9,y=0; try { int z=x/y; } catch(DivideByZeroException e) { Console.WriteLine(&Divide by the zero&); //处理语句 } } } //获取异常 //0 作为除数,产生异常运行上面的程序,会得到如下的结果:Divide by the zero上面的范例程序是系统在发现问题时,自动抛出的异常。程序设计人员也可以在某些条 件下,用 throw 关键词让程序产生异常,并用 catch 来获取异常并处理。using S public class ExpectionExmaple { public static void Main() ?39? { int x=9,y=0; try { int z=x*y; if(z==0) throw new Exception(); } catch(Exception e) { Console.WriteLine(&zero in the mutiple&); //处理语句 } } } //获取异常 //自行控制抛出异常在正常情况下,乘数里有 0 的话并不会发生任何异常,但是这里设计用 throw 来抛出一 个异常,于是便可以用 catch 来获取异常并处理。7 小结C#是微软推出的专门用于.NET 平台的一门新型面向对象语言。它简洁、先进、类型安 全,而且在网络编程方面,特别是 ASP.NET 网络开发方面,有着强大的功能,因此应用十分 广泛。 本章主要地介绍了 C#语言中最基础、也是最常用的一些知识,详细地讲解了面向对象 语言的主要特点。这些内容足以让读者在 ASP..NET 中任意翱翔,大展拳脚。但是如果没有 面向对象编程基础的话,要全面理解本章的内容还是有点难度。不过这不会影响以后的课程 学习,随着 ASP.NET 介绍的慢慢深入,学习更多的例子后,读者自然会对 C#得心应手。?40?
赞助商链接

我要回帖

更多关于 matlab 未定义 double 的文章

 

随机推荐