标题:C#基础入门
只看楼主
燃燒
Rank: 9Rank: 9Rank: 9
来 自:磁盘驱动器
等 级:贵宾
威 望:56
帖 子:9878
专家分:2
注 册:2006-4-20
结帖率:0
 问题点数:0 回复次数:29 
C#基础入门
C#读作C Sharp,作为Microsoft的下一代面向对象的语言,能够让开发人员在.NET平台上快速地建立大量的应用程序。按照Microsoft给出的定义,C#是一种源自于C和C++的,简单的、现代的、面向对象的和类型安全的程序设计语言。C#为程序员提供了开发飞速发展的Web应用程序所需要的强大而灵活的功能。与C++相比,C#将更容易被人们理解和接受,未来大量.NET平台的应用将由C#开发,C#将是未来开发企业级分布式应用程序的首选。

  #1 一、C#的特点

   C#就是这样一种编程语言,它使程序员能快速地为新一代Microsoft .NET平台开发出应用程序。具体来说,微软的C#具有如下特点:

   1.快速应用开发(RAD)功能

   支持快速开发(Rapid application development,RAD)可以说是目前开发语言最为重要的一大功能,支持快速开发可以使得开发人员的开发效率倍增,从而使得他们可以从繁重的重复性劳动中解放出来。

   C#的RAD功能主要表现在垃圾收集、指代等特性上。垃圾收集机制将减轻开发人员对内存的管理负担,而指代功能更是可以让开发者不经过内部类就调用函数。利用C#的这些功能,可以使开发者通过较少的代码来实现更强大的应用程序,并且能够更好地避免错误发生,从而缩短了应用系统的开发周期。

   2.语言的自由性

   用C#编写的程序能最大程度地和任何支持.NET的语言互相交换信息。能够继承和使用任何语言所编写的程序,这样做的好处是节省了大量的工作,你不必把COBOL等语言强行改成另一种语言,.NET让各种语言真正地互相交流了。

   3.强大的Web服务端组件

   在C#的Web编程中,最让人兴奋的是Web服务端的组件,它们不仅包括传统组件,还包括那些能够自动连接服务的可编程组件,你可以用C#编写自己的服务器端组件,使用它们可以更自由、更容易地进行数据绑定。

   4.支持跨平台

   随着互联网应用程序的应用越来越广,开发人员所设计的应用程序必须具有强大的跨平台性。C#编写的应用程序就具有强大的跨平台性,这种跨平台性也包括了C#程序的客户端可以运行在不同类型的客户端上,比如PDA、手机等非PC装置。

   5.与XML的融合

   由于XML技术真正融入到了.NET之中,C#的编程变成了真正意义的网络编程,甚至可以说.NET和C#是专为XML而设计,使用C#的程序员可以轻松用C#内含的类来使用XML技术。就这方面而言,目前C#提供给了程序员裹多的自由和更好的性能来使用XML。

   6.对C++的继承

   C#继承并保留了C++强大的功妮,例如, C#保留了类型安全的检测和重载功能,C#还提供了一些新功能取代了一些原来的ANSI C预处理程序的功能,提高了语言的类型安全等安全性。

  #1 二、简单应用程序举例与分析

   在全面、系统地学习以前,我们先来看一个C#的经典程序“Welcome”。

   1.Welcome程序

   第一个程序总是很简单的,我们让用户通过键盘输入自己的名字,然后程序会在屏幕上打印出一条欢迎信息。程序代码如下:

   //源文件:welcome.cs

   using System;

   class Welcome

   {

   static void Main(){

   Console.WriteLine("Please enter your name:");

   //要求用户输入姓名;

   Console.ReadLine();//读取用户输入;

   Console.WriteLine("Welcome to you!");

   /*本行代码用于打印欢迎信息;

   你可以在这里添加自己的代码;

   程序结束*/

   }

   }

   上面的代码你可以在任意一种字处理软件中进行编写,然后以文件名“Welcome.cs”存盘。典型的C#源文件都是以“.cs”作为文件的扩展名的。

   注意:C#语言是大小写敏感的。

   2.代码分析

   (1)名字空间

   using System表示导入名字空间。如果你熟悉C或者C++编程,那么你一定经常使用“#include”之类的语句来导入其他C或者C++源文件。C#的含义与此类似,用于导入预定的元素。“System”就是一个名字空间,“using”指令允许对属于该名字空间成员的类型无限制引用。

   (2)类和类的方法

   在程序第二行,class Welcome声明了一个类,类的名字叫做“Welcome”。这个程序让我们所作的事情都依靠它来完成。

   Static void Main()表示类“Welcome”中的一个方法,方法总是为我们完成某项工作的。在C#中,程序的执行总是从“main()”方法开始,一个程序中不允许出现两个或者两个以上的“main()”方法。

   就像一个文件夹可以容纳多个文件一样,一个名字空间可以被视为某些类的一个容器。因为.NET有很多类,所以名字空间是必要的。微软已经编写了数以千计的基类,同吮任何合理的大型应用程序都可以定义更多的类。通过把类放入名字空间可以把相关的类组织起来,并且可以避免命名冲突。

   (3)“{”和“}”

   与C和C++一样,源代码被包含在一对大括号之中,每一个右括号总是和它前面离它最近的一个左括号相配套。如果左括号和右括号没有全部的配套,那么这就是一个错误的程序。所有语句都以分号“;”结束。

   (4)程序的输入与输出

   程序所完成的输入输出功能都是通过“Console”来完成的,“Console”是在名字空间“System”中已经定义好的一个类,你根本不需要管它是怎么完成工作的,只要直接使用它就可以了。

   上面的程序代码中,类“Console”为我们展现了两个最基本的方法:ReadLine和WriteLine。Console.ReadLine表示接受输入设备输入,Console.WriteLine用于在输出设备中输出。

   3.运行程序

   (1)执行代码

   理解了源程序中每一条代码的具体含义后,下一步我们要做的就是让这个程序真正能够运行。

   如果你的计算机上安装了Visual Studio .NET,则可以在集成开发环境(Integrated Developer Environment,IDE)中直接编译并执行源文件。如果你不具备这个条件,那么安装Microsoft .NET Framework SDK也是可以的。实际上,.NET平台内置了C#的编译器。下面让我们使用微软提供的命令行编译器来对上面的程序进行编译。

   启动一个命令提示符,输入一行命令:

   csc welcome.cs

   此时,Welcome.cs文件将被编译并运行,屏幕上会出现一行字符,提示你输入姓名:

   Please enter your name:

   输入任意安符并回来确认,屏幕是将打印出欢迎信息:

   Welcome to you!

   在C#中,编译器只执行编译过程,而在C或者C++中要经过编译和链接两个阶段。也就是说,C#源文件并不被编译成目标文件(.obj),而是直接生成可执行文件(.exe)或动态链接库(.dll)。C#编译器中不需要包含链接器。

   (2)命令行编译器选项

   我们可以灵活地使用.NET平台提供的命令行编译器的不同选项,选择不同的编译方式。

   例如,我们希望对源文件进行编译,生成一个名为MyWelcome.exe的可执行文件,我们可以采用下面的命令:

   csc/out MyWelcome.exe Welcome.cs

   有如不同的命令参数一样,不同的命令行编译器选项会影响我们编译执行的结果,如果不知道各个选项的具体含义,你可以通过编译器帮助来获得:

   csc/?

   4.添加注释

   C#中注释的方式和C、C++没有什么区别,每行中双斜杠“//”后面的内容,以及在分割符“/*”和“*/”之间的内容都将被编译器忽略。其中,“//”表示进行单行注释;“/*”和“*/”表示多行注释。

  #1 三、C#语言基础

   (一)数据类型

   应用程序总是要处理数据的,我们必须要让计算机了解需要处理什么样的数据,用什么方式进行处理,按什么格式保存数据等。这就需要了解程序设计语言的数据类型。

   1.值类型

   在学习各种类型以前,我们先提一下变量的概念,变量即是存储信息的基本单元,另一方面,我们也可以把变量理解为计算机内存中的一个存储空间。C#的值类型可以分为:简单类型、结构类型、枚举类型。

   简单类型是直接由一系列元素构成的数据类型。C#中为我们提供了一组已定义的简单类型。这些简单类型可分为:整数类型、布尔类型、字符类型和实数类型。

   (1)整数类型

   整数类型的变量的值为整数。C#中有九种整数类型:短字节型(sbyte)、字节型(byte)、短整型(short)、无符号短整型(ushort)、整型(int)、无符号整型(uint)、长整型(long)、无符号长整型(ulong)。这些整型类型在数学上的表示以及在计算机中的取值范围如下表所示。

   (^60090201g^)

   (2)布尔类型

   布尔类型是用来表示一个事件或状态的“真”和“假”。我们知道,不管任何数据,在计算机的内部都是采用二进制方式处理和存储。布尔类型表示的逻辑变量只有两种取值:“真”或“假”,在C#中分别采用“true”和“false”表示。

   (3)实数类型

   浮点类型:数学中的实数不仅包括整数,而且包括小数。小数在C#中采用单精度(float)和双精度(double)。它们的差别在于取值范围和精度不同。

   单精度:取值范围在(^60090201a)^到(^60090201b^)之间,精度为7位数。

   双精度:取值范围在(^60090201c^)到(^60090201d^)之间,精度为15到16位数。

   十进制类型(decimal):是C#专门为我们定义的一种数据类型,主要用于方便我们在金融和货币方面的计算。C#通过提供这种专门的数据类型,使我们能够更快捷地设计这方面的应用程序。其取值范围从大约(^60090201e^)到(^60090201f^)的28到29位有效数字。

   当定义一个十进制变量并赋值给它时,使用m下标以表明它是一个十进制类型。如果省略了m下标,在变量被赋值之前,它将被编译器当作双精度数据类型来处理。下面是一个合法的赋值:

   decimal d_value=1.0m;

   (4)字符类型

   除了数字以外,计算机还需要处理的信息主要就是字符了。字符包括数字字符、英文字符、表达符号等,C#提供的字符类型采用了国际公认的Unicode字符集标准。一个Unicode的标准字符长度为16位,用它可以表示大多数的字符类型了。可以按下面的方法给一个字符变量赋值,如:

   char c=′A′;

   另外,我们还可以直接通过十六进制转义符(前缀\x)或Unicode表示法给字符型变量赋值)(前缀\u),用来在程序中指代特殊的控制字符。

   (5)结构类型

   在具体的程序设计中我们经常要把一组相关的信息存放在一起。把一系列相关的变量组织成为一个单一实体的过程,称为生成结构的过程。这个单一实体的类型我们就叫做结构类型,每一个变量称为结构的成员。结构类型的变量采用struct来进行声明。下面的程序代码说明定义一个通讯录记录结构(包括姓名、电话和地址)的定义。

   Struct PhoneBook{

   public string name;

   public string phone;

   public string address;

   }

   PhoneBook p1;

   p1就是一个通讯录(PhoneBook)结构类型的变量。上面声明中的“public”表示对结构类型的成员的访问权限。对结构成员的访问通过结构变量名加上访问符“.”号,后跟成员的名称:

   p1.name=″tom″;

   结构类型包含的成员类型没有限制,可以相同也可不同。

   (6)枚举类型

   枚举(enum)实际上是为一组在逻辑上密不可分的整数值提供便于记忆的符号。下面的程序代码声明了一个代表星期的枚举类型的变量。

   Enum WeekDay{

   Sunday,Monday,Tuesday,Wednesday,Friday,Saturday

   };

   WeekDay day;

   注意:枚举类型的变量在某一时刻只能取枚举中某一个元素的值。如,day这个表示“星期”的枚举的变量,它的值要么是Sunday,要么是Monday或其他的星期元素,但它在一个时刻只能代表具体的某一天,不能既是星期二,又是星期三。

   Day=Tuseday;

   按照系统默认,枚举中的每个元素都是整型(int),且第一个元素删去的值为0,它后面的每一个连续的元素的值按加1递增。在枚举中,也可以给元素直接赋值。下面的程序代码把星期一的值设为1,其后的元素的值分别为2,3……

   enum WeekDay{

   Sunday=1,Monday,Tuesday,Wednesday,Friday,Saturday

   };

   为枚举类型的元素所赋值的值的类型限于long、int、short和byte等整数类型。

   2.引用类型

   在这里,引用的含义是该类型的变量不直接存储所包含的值,而是指向它所要存储的值。即引用类型存储实际数据的引用值的地址。C#中的引用类型有四种:类、代表、数组和接口。

   (1)类

   类是面向对象编程的基本单位,是一种包含数据成员、函数成员和嵌套类型的数据结构。类的数据成员有常量、域和事件。函数成员包括方法、属性、索引指示器、运算符等。类和结构同样都包含了自己的成员,但它们之间最主要的区别在于:类是引用类型,而结构是值类型。

   类支持继承机制,通过继承,派生类可以扩展基类的数据成员和函数成员,进而达到代码重用和设计重用的目的。下面介绍两个经常用到的类:

   object类:它是所有其他类型的基类,C#中的所有类型都直接或是间接地从object类中继承。因此,对一个object的变量可以赋予任何类型的值。

   Int x=25;

   object obj1;

   obj1=x;

   object obj2=′A′;

   对object类型的变量声明采用object关键字,这个关键字是在.NET平台中为我们提供的预定义的名字空间System中定义的,是类System.Object的别名。

   String类:专门用于对字符串的操作。同样,这个类也是在.NET平台中为我们提供的预定义的名字空间System中定义的,是类System.String的别名。

   字符串在实际中应用非常的广泛,在类的定义中封装了许多内部的操作,我们只要简单地加以利用就可以了。可以用加号“+”合并两个字符串,采用下标从字符串中获取字符等。

   String String1=″Welcome″;

   string String2=″Welcome″+″everyone″;

   char c=String1[0];

   bool b=(String1==String2);

   (2)代表

   在C#中取消了C和C++中的指针的这个概念。而代表实际上相当于是C#中的函数指针原型,与指针不同的是,代表在C#中是类型安全的。

   在声明代表时,只需要指定代表指向的原型的类型,它不能有返回值,也不能带有输出类型的参数。如我们可以声明一个指向int类型函数原型的代表:

   delegate int MyDelegate();

   如果我们声明了自己的一个代表,那么它就是对系统定义的类System.deldgate的一个扩展。

   (3)数组

   在进行批量处理数据的时候,我们要用到数组。数组是一组类型相同的有序数据。数组按照数组名、数据元素的类型和维数来进行描述。C#中提供Ststem.Array类是所有数组类型的基类。

   数组的声明格式为:

   non-array-type[dim-separators] array-instance name;

   比如我们声明一个整数数组:

   int[]arr;

   在定义数组时,可以预先指定数组元素的个数,这时在“[]”中定义数组的元素个数,它的个数可以通过数组名加圆点加“Length”获得。而在使用数组时,可以在“[]”中加入下标来取得对应的数组元素。C#中的数组元素的下标是从0开始的,以后递增。

   在C#中数组可以是一维的也可以是多维的,同样也支持矩阵和参差不齐的数组。其中一维数组最为普遍,用得也最多。

   Class Tese

   {

   static void Main(){ //可动态生成数组的长度

   string[] a1; //一维数组string

   string[] a2; //二维数组string

   string[] a3; //三维数组string

   }

   }

   (4)接口

   接口定义了一个协议(conrtact)。一个类或结构要实现接口就必须坚持这种协议。接口可以包括方法、属性、索引和事件作为成员。下面的程序代码说明了一个接口,它包含一个索引、一个事件E、一个方法F和一个属性P。

   Interface Iexampie

   {

   string this[int index]{get; ste;}\

   event EventHandler E;

   void F(int value);

   string P{get; set;}

   }

   (二)变量与常量

   相信你应该对变量和常量的概念再熟悉不过了,有关变量和常量的知识都是任何一门编程语言的基础知识,而每一门编程语言都有自己相对应的变量和常量的命名规则和使用方式。

   1.变量

   (1)变量的概念

   程序要对数据进行读、写、运算等操作,当需要保存特定的值或计算结果时,就需要用到变量(Variable)。在用户看来,变量是用来描述一条信息的名称,在变量中可以存储各种类型的信息,如姓名、价格、文件的长度等。在计算机中变量代表存储地址,变量的类型决定了存储在变量中的类型,C#是一种安全类型语言,它的编译器存储在变量中的数值具有适当的数据类型。同时,变量的值可以通过赋值被改变。

   使用变量的一条重要的原则是:变量必须先定义后使用。

   (2)变量的类型

   在C#中,我们把变量分为七种:静态变量、非静态变量、局部变量、数组元素、值参数、引用参数和输出参数等。

   静态变量:带有“static”修饰符声明的变量称为静态变量。一旦静态变量所属的类被装载,直到包含该类的程序运行结束时它将一直存在。静态变量就是该变量类型的默认值。静态变量最好是在定义时便赋值。如static a =10;

   非静态变量:不带有“static”修饰符声明的变量称其为实例变量。如int a;类中的非静态变量,一旦一个类的新的实例被创建,直到该实例不再被应用从而所在空间被释放为止,该非静态变量将一直存在。同样鉴于定义赋值检查,一个类的非静态变量也应该是在初始化的时候赋值。

   数组元素:数组元素也是变量的一种,该变量随该数组实例的存在而存在。每一个数组元素的初始值是该数组元素类型的默认值。同样地,鉴于定义赋值检查,数组元素最好是在初始化的时候被赋值。

   局部变量:局部变量是指在一个独立的程序块中,一个for语句、switch语句或者using语句中声明的变量,它只在该范围内有效。当程序运行到这个范围内时,该变量即开始生效,程序离开时变量失效。与其他几种变量类型不同的是,局部变量不会自动被初始化,所以也就是没有默认值。在进行赋值检查时,局部变量被认为没有被赋值。

   在局部变量的有效范围内,在变量的定义以前就使用是不合法的。如下面的代码:

   for(int I=0;I<10;I++){

   int num=a; //这是非法的,因为局部变量a还没有被定义

   int a;

   int b=a;

   }

   有关值参数、引用参数和输出参数在这里我们不作讨论,有兴趣的读者可以参看相关的书藉。

   2.常量

   所谓常量就是其值固定不变的量。从数据类型来讲,常量的类型可以是任何一种值类型或者是引用类型。一个常量的声明,就是声明程序中要用到的常量的名称和它的值,与变量一样,我们可以同时声明一个或者多个给定类型的常量。常量声明的格式如下:

   attributes constant-modifiers const type constant-declarators;

   其中:常量修饰符constant-modifiers可以是:new、public、protected、internal、private。

   常量的类型type必须是下面中的一种:

   sbyle、byte、short、ushort、int、uint、ulong、char、float、double、decimal、bool、string或是引用类型(reference-type)。

   常量表达式constant-declarators表示常量的名字。

   如:public const double X=1.0,Y=2.0,Z=3.0;
搜索更多相关主题的帖子: 入门 基础 
2007-12-11 14:14
燃燒
Rank: 9Rank: 9Rank: 9
来 自:磁盘驱动器
等 级:贵宾
威 望:56
帖 子:9878
专家分:2
注 册:2006-4-20
得分:0 
(三)表达式

   C#语言中的表达式类似于数学运算中表达式,它是操作符、操作对象和标点符号等连接而成的式子。操作符是用来定义类实例中表达式操作符的。表达式是指定计算的操作符、操作数序列。

   1.操作符的分类

   表达式由操作数和操作符组成。表达式的操作符指出了对操作数的操作。比如操作符有+、-、/;操作数可以是文字、域、当前变量或表达式。

   依照操作符作用的操作数的个数来分,C#中有一元操作符:作用于一个操作数,包括前缀操作符和后缀操作符;二元操作符:作用于两个操作数,使用时在操作数中插入操作符;三元操作符:只有一个操作符“?:”。作用于三个操作数,使用时在操作数中间插入操作符。

   下面分别给出使用操作符的例子:

   int x=5,y=10,z;

   x++; //后缀一元操作符

   --x; //前缀一元操作符

   z=x+y; //二元操作符

   y=(X>10?0:1); //三元操作符

   2.操作符的优先级

   当一个表达式包含多样操作符时,操作符的优先级控制着单个操作符求值的顺序。例如,表达式x+y*z按照x+(y*z)求值,因为“*”操作符比“+”操作符有更高的优先级。下表给出了所以操作符从高到底的优先级顺序。

   (^60090201h^)

   当一个操作数出现在两个有相同优先级的操作符之间时,操作符按照出现的顺序由左至右执行。除了赋值的操作符,所有的二进制操作符都是按照从左向右的顺序执行。如x+y+z按(x+y)+z进行。

   赋值操作符和条件操作符(?:)按照从右向左的顺序执行。如x=y=z按照x=(y=z)进行。

   建议:在写表达式时,如果无法确定操作符的有效顺序,则尽量采用括号来保证运算的顺序,这样也使得程序一目了然,而且自己在编程时能够思路清晰。

   (四)流程控制

   在前面众多的程序代码中,我们的程序都还只能按照编写的顺序执行,中途不能发生任何的变化。为了适应需要,我们经常要转移或者说是要改变程序执行的顺序,达到这些目的的语句就是流程控制语句。

   1.条件语句

   当程序中需要进行两个或两个以上的选择时,可以根据条件判断来选择将要执行的一组语句。C#提供的选择语句有if语句和switch语句。

   (1)if语句

   if语句是最常用的选择语句,它根据布尔表达式的值来判断是否执行后面的内嵌语句。其格式为:

   if(boolean-expression)embedded-statement或

   if(boolean-expression)embedded-statement

   else embedded-statement

   当布表达式的值为真时,则执行if后面的内嵌语句embedded-statement。为假时则程序继续执行。如果有else语句时,则执行else后面的内嵌语句,否则继续执行下一条语句。

   If (x-int(x)>0.5

   {

   I=int(x)+1;

   }

   else

   {

   I=int(x)

   }

   如果if或者else之后的嵌套语句只包含一条执行语句,则嵌套部分的大括号可以省略。如果包含了两条以上的执行语句,对嵌套部分一定要加上大括号。

   如果程序的逻辑判断关系比较复杂,通常会采用条件判断嵌套语句。If语句可以嵌套使用,即是在判断之中又有判断。具体的形式如下:

   if(boolean-expression)

   {

   if(boolean-expression)

   {……};

   else

   {……};

   ……

   }

   else

   {

   if(boolean-expression)

   {……};

   else

   {……}

   ……

   }

   此时应注意,每一条else与离它最近且没有其他else与之对应的if相搭配。

   (2)Switch语句

   if语句每次判断只能实现两条分支,如果要实现多种选择的功能,那么可以采用Switch语句。Switch语句根据一个控制表达式的值选择一个内嵌语句分支来执行。它的一般格式为:

   switch(controlling-expression)

   {

   case constant-expression;

   embedded-statements

   default;

   embedded-statements

   }

   Switch语句的控制类型,即其中控制表达式(controlling-expression)的数据类型可以是sbyle、byte、short、short、uint、long、ulong、char、string或是枚举类型(rnum-type)。每个case标签中的常量表达式(constant-expression)必须属于或能隐式转换成控制类型。如果有两个或两个以上case标签中的常量表达式值相同,编译时将报错。Switch语句中最多只能有一个default标签。

   下面的程序代码说明Swtich语句按所提供参数的数字执行不同的语句。

   Using system;

   class Test

   {

   static void Main (string[] args) {

   switch (args.Length) {

   case 0;

   Console.WriteLine ("No arguments were provided");

   break;

   case 1;

   Console.WriteLine ("One arguments was provided");

   break;

   default;

   Console.WriteLine ("{0} arguments were provided");

   break;

   }

   }

   }

   2.循环语句

   循环语句可以实现一个程序模块的重复执行,它对于我们简化程序,更好地组织算法有着重要的意义。C#提供了四种循环语句:While语句、do-while语句、for语句、foreach语句。

   (1)While语句

   While语句有条件地将内嵌语句执行0遍或若干遍。其格式为:

   while (boolean-expression) embedded-statement

   其执行的顺序是:

   首先计算表达式boolean-expression的值;当布尔表达式的值为真时,执行语句embedded-statement一遍,程序转至第1步;当布尔表达式的值为假时,while循环结束。

   (2)do-while语句

   do-while语句与while语句不同的是,它将内嵌语句执行一次(至少一次)或若干次。其格式为:

   do embedded-statement while(boolean-expression)

   其执行的顺序是:

   首先执行内嵌语句embedded-statement一遍;当布尔表达式的值为真时则回到第1步,为假时则终止do循环。

   在do-while循环语句中同样允许用break语句和continue语句实现与while语句中相同的功能。

   (3)for语句

   for语句是C#中使用频率最高的循环语句。在事先知道循环次数的情况下,使用for语句是比较方便的。其格式为:

   for(inttializer,condinton;iterator)embedded-statement

   其中inttializer、condinton、iterator三项是可选项。Inttializer为循环控制变量做初始化,循环控制变量可以有一个或多个(用逗号隔开);condinton为循环控制条件,也可以有一个或多个语句;iterator按规律改变控制变量的值。

   其执行的顺序是:

   首先按照书写顺序将inttializer部分(如果有)执行一遍,为循环控制变量赋初值;然后测试condinton(如果有)中的条件是否满足;若没有condinton项或条件满足,则执行内嵌语句一遍,按iterator改变循环控制变量的值,回到第2步执行;若条件不满足,则for循环终止。

   下面的程序代码说明用一个for语句写出整数1~10。

   Using System;

   class Test

   {

   static void Main(){

   for (int I=0; I<10; I++)

   Console.WriteLine(I);

   }

   }

Thinking in life, thinking in love, thinking in dream,thinking in you !
月光倾泻,岁月沉沦
[url=http://58189.]http://58189.[/url]
2007-12-11 14:16
燃燒
Rank: 9Rank: 9Rank: 9
来 自:磁盘驱动器
等 级:贵宾
威 望:56
帖 子:9878
专家分:2
注 册:2006-4-20
得分:0 
(4)foreach语句

   foreach语句是在C#中新引入的。它表示收集一个集合中的各元素,并针对各个元素执行内嵌语句。其格式为:

   foreach(type identifier in expression)embedded-statement

   其中类型(type)和标识符(identifier)用来声明循环变量,表达式(expression)对应集合。每执行一次内嵌语句,循环变量就依次取集合中的一个元素代入其中。在这里,循环变量只是一个只读型局部变量,如果试图改变它的值或将它作为一个ref或out类型的参数传递时,都将引发编译出错。

   Foreach语句中的expression必须是集合类型,如果该集合的元素类型与循环变量类型不一样,则必须有一个显示定义的从集合中的元素类型到循环变量元素类型的显示转换。

   下面的程序代码说明用一个foreach语句来循环显示列表中的元素。

   Using System;

   using System.Collections;

   class Tese

   {

   static void WriteList(Arraylist list){

   foreach(object o in list)

   Console.WriteLine(o);

   }

   static void Main(){

   ArrayList list=new ArrayList();

   for(int I=0; I<10; I++)

   list.Add(I);

   WriteList(list);

   }

   }

   3.转子语句

   (1)break语句和continue语句

   break语句用来退出最近的switch、while、do、for、foreach语句的循环,而continue语句用来开始一个新的while、do、for和foreach语句的循环。

   (2)标签声明和goto声明

   标签声明可以交替声明,goto声明可以把控制传送到标签声明。

   (3)return语句

   return语句返回对语句中的成员控制。无表达式的return语句只能在无返回值的成员中应用。带表达式的return语句只能在返回表达式的函数成员中运用。

   (4)throw语句与try语句

   throw语句用来抛出异常。Try语句提供一个在程序块执行过程中捕获异常的机制。此外,try语句还提供当try语句脱离控制时总是要执行的代码块。

   (五)异常处理

   程序中对异常的处理能使你的程序更加强壮。现在的许多程序设计语言都增加了异常处理的能力,C#也不例外。

   1.异常处理语句

   C#中的异常处理语句有三种形式:try-catch 捕捉异常、try-finally 清除异常、try-catch-finally 处理所有异常。

   下面的一段代码处理溢出异常:

   try{

   for(;n<=max;n++)

   sum*=n;

   }

   catch(OverfolwException oe)

   {

   Console.WriteLine(“溢出“);

   return;

   }

   2.清除异常

   try-finally 结构将清除异常。看下面的代码:

   try{

   for(;n<=max;n++)

   sum*=n;

   }

   finally

   {

   Console.WriteLine(“溢出“);

   return;

   }

   上面的代码中finally 子句中的代码在任何情况下总会被执行,即使没有异常发生。

   3.处理所有异常

   try-catch-finally 处理所有的异常。如下面的代码:

   try{

   for(;n<=max;n++)

   sum*=n;

   }

   catch(OverfolwException oe)

   {

   Console.WriteLine(“溢出“);

   return;

   }

   catch(Exception e)

   {

   //捕捉所有异常

   }

   finally

   {

   }

   4.抛出异常

   程序中我们可以先抛出异常,然后进行捕捉。

   抛出异常的语法如下:

   throw new Exception()

  #1 四、一个简单的客户应用程序

   有了上面的基础,通过下面的实例可以轻松掌握如何创建组件和一个简单的客户应用程序。

   1.构建组件

   首先在文本编器中编写源代码,以下是两个文件add.cs,mult.cs的程序代码。

   //add.cs

   using System;

   public class AddClass

   {

   public static long Add(long I,long j)

   {

   return(I+j);

   }

   }

  

   //mult.cs

   using System;

   public class MultiplyClass

   {

   public static long Multiply(long x,long y)

   {

   return(x*y);

   }

   }

   以上代码定义了两个类AddClass和MultipyClass,并分别构造了两个方法Add()和Multiply()。

   2.编译组件

   csc/target:library/out:MyLibrary.dll Add.cs Mult.cs

   通过csc把Add.cs和Mult.cs两个文件编译成类型库MyLibrary.dll。

   3.客户应用程序调用

   客户应用程序调用组件的方法如下:

   //MyClient.cs

   using System;

   class MyClient

   {

   public static void Main(string[ ] args)

   {

   Console.WriteLine("Calling methods from MyLibrary.dll:");

   if (args.Length !=2)

   {

   Console.WriteLine("Usage:MyClient <numl> <num2>");

   return;

   }

   long num1=long.Parse(args[0]);

   long num2=long.Parse(args[1]);

   long sum=AddClass.Add(num1,num2);

   long product=MultiplyClass.Multiply(num1,num2);

   Console.WriteLine("The sum of {0} and {1} is {2}",num1,num2,sum);

   Console.WriteLine("The product of {0} and {1} is {2}",num1,num2,product);

   }

   }

   在编译客户应用程序时,引用了上面编译好的新组件库MyLibrary.dll,然后运行MyClient.exe文件得到结果。

   Csc/out:MyClient.exe/reference:MyLibrary.dll MyClient.cs

   4.执行结果

   在命令行输入:

   >MyClient 2 3 (回车)

   5.输出结果

   Calling methods from MyLibrary.dll:

   The sum of 2 and 3 is 5

   The product of 2 and 3 is 6

   以上的组件并没有使用名字空间,如果构建组件的文件中添加了名字空间的语句,如下:

   using System;

   namespace MyMethods

   {

   public class …

   {

   public static long …(long I, long j)

   {

   …

   }

   }

   }

   那么,在客户应用程序中将使用引导名字空间的语句,这样程序才会根据名字空间的方向找到应用的类和方法。例如:

   //MyClient.cs

   using System;

   using MyMethods;

   class MyClient

   {

   …

   }

   以上名字空间的好处在于一个空间定义多个类或是名字空间再包括其他名字空间,这样可以降低编译程序的出错率。

Thinking in life, thinking in love, thinking in dream,thinking in you !
月光倾泻,岁月沉沦
[url=http://58189.]http://58189.[/url]
2007-12-11 14:16
燃燒
Rank: 9Rank: 9Rank: 9
来 自:磁盘驱动器
等 级:贵宾
威 望:56
帖 子:9878
专家分:2
注 册:2006-4-20
得分:0 
#1 五、一个GUI例子

   该例子中有一个文本框,两个按钮,单击“点击我”的按钮在文本框中显示“你好,电脑报”。单击“终结者”的按钮结束程序。

   Using System;

   using System.Drawing;

   using System.Collections;

   using

   using System.Windows.Forms;

   using System.Data;

  

   namespace WindowsApplication1

   {

   /// <summary>

   /// Summary description for Form1.

   /// </summary>

   public class Form1 : System.Windows.Forms.Form

   {

   private System.Windows.Forms.TextBox textBox1;

   private System.Windows.Forms.Button button1;

   private System.Windows.Forms.Button button2;

   /// <summary>

   /// Required designer variable.

   /// </summary>

   private components = null;

  

   public Form1()

   {

   //

   // Required for Windows Form Designer support

   //

   InitializeComponent(); //初始化窗体及子控件

  

   //

   // TODO: Add any constructor code after InitializeComponent call

   //

   }

  

   /// <summary>

   /// Clean up any resources being used.

   /// </summary>

   protected override void Dispose( bool disposing ) //释放对组件的引用,以便垃

   { //圾回收器回收无用的内存

   if( disposing )

   {

   if (components != null)

   {

   components.Dispose();

   }

   }

   base.Dispose( disposing );

   }

  

   #region Windows Form Designer generated code

   /// <summary>

   /// Required method for Designer support - do not modify

   /// the contents of this method with the code editor.

   /// </summary>

   private void InitializeComponent()

   {

   this.textBox1 = new System.Windows.Forms.TextBox();

   this.button1 = new System.Windows.Forms.Button();

   this.button2 = new System.Windows.Forms.Button();

   this.SuspendLayout();

   //

   // textBox1

   //

   this.textBox1.Location = new System.Drawing.Point(74, 64);

   this.textBox1.Name = "textBox1";

   this.textBox1.Size = new System.Drawing.Size(144, 21);

   this.textBox1.TabIndex = 0;

   this.textBox1.Text = "C#酷吗?";

   //

   // button1

   //

   this.button1.Location = new System.Drawing.Point(58, 160);

   this.button1.Name = "button1";

   this.button1.Size = new System.Drawing.Size(72, 24);

   this.button1.TabIndex = 1;

   this.button1.Text = "点击我";

   this.button1.Click += new System.EventHandler(this.button1OnClick);

   //

   // button2

   //

   this.button2.Location = new System.Drawing.Point(162, 160);

   this.button2.Name = "button2";

   this.button2.Size = new System.Drawing.Size(72, 24);

   this.button2.TabIndex = 2;

   this.button2.Text = "终结者";

   this.button2.Click += new System.EventHandler(this.button2OnClick);

   //

   // Form1

   //

   this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);

   this.ClientSize = new System.Drawing.Size(292, 273);

   this.Controls.AddRange(new System.Windows.Forms.Control[] {

   this.button2,

   this.button1,

   this.textBox1});

   this.Name = "Form1";

   this.Text = "我爱C#";

   this.ResumeLayout(false);

  

   }

   #endregion

  

   /// <summary>

   /// The main entry point for the application.

   /// </summary>

   [STAThread]

   static void Main()

   {

   Application.Run(new Form1()); //启动程序

   }

  //响应单击按钮“点击我”的button1OnClick事件

  private void button1OnClick(object sender, System.EventArgs e)

   {

   textBox1.Text="你好!电脑报";

   //

   }

  

  //响应单击按钮“终结者”的button2OnClick事件

   private void button2OnClick(object sender, System.EventArgs e)

   {

   Application.Exit(); //退出应用程序

   }

  }

  }

Thinking in life, thinking in love, thinking in dream,thinking in you !
月光倾泻,岁月沉沦
[url=http://58189.]http://58189.[/url]
2007-12-11 14:17
tianya100
Rank: 1
等 级:新手上路
帖 子:20
专家分:0
注 册:2007-9-19
得分:0 
不错

我就像一只趴在玻璃上的苍蝇,前途一片光明,而我却找不到出路。
2007-12-11 14:51
燃燒
Rank: 9Rank: 9Rank: 9
来 自:磁盘驱动器
等 级:贵宾
威 望:56
帖 子:9878
专家分:2
注 册:2006-4-20
得分:0 
由于工作需要 正在学习 C# 大家有好的东东 拿出来分享下 ~~

Thinking in life, thinking in love, thinking in dream,thinking in you !
月光倾泻,岁月沉沦
[url=http://58189.]http://58189.[/url]
2007-12-11 16:00
guoxhvip
Rank: 8Rank: 8
来 自:聖西羅南看臺
等 级:贵宾
威 望:44
帖 子:4052
专家分:135
注 册:2006-10-8
得分:0 
支持热心的楼主

愛生活 && 愛編程
2007-12-11 16:14
tanxiaolin
Rank: 1
等 级:新手上路
帖 子:71
专家分:0
注 册:2007-12-12
得分:0 
大家有没有使用dataGridView1分页显示好的方法呢

求各位高手帮忙。
2007-12-12 09:59
燃燒
Rank: 9Rank: 9Rank: 9
来 自:磁盘驱动器
等 级:贵宾
威 望:56
帖 子:9878
专家分:2
注 册:2006-4-20
得分:0 
C#选择控制语句
我们所介绍的第一个选择语句是"if"语句,它有三种基本形式:单条选择, 如果/否则,以及多情形选择。

1.清单3-1. IF语句的格式:IfSelection.cs

using System;
class IfSelect {
public static void Main() {
string myInput;
int myInt;
Console.Write("Please enter a number: ");
myInput = Console.ReadLine();
myInt = Int32.Parse(myInput);
// Single Decision and Action with brackets
if (myInt > 0) {
Console.WriteLine("Your number {0} is greater than zero.", myInt);
}
// Single Decision and Action without brackets
if (myInt < 0)
Console.WriteLine("Your number {0} is less than zero.", myInt);
// Either/Or Decision
if (myInt != 0) {
Console.WriteLine("Your number {0} is not equal to zero.", myInt);
}
else {
Console.WriteLine("Your number {0} is equal to zero.", myInt);
}
// Multiple Case Decision
if (myInt < 0 || myInt == 0) {
Console.WriteLine("Your number {0} is less than or equal to zero.", myInt);
}
else if (myInt > 0 && myInt <= 10) {
Console.WriteLine("Your number {0} is between 1 and 10.", myInt);
}
else if (myInt > 10 && myInt <= 20) {
Console.WriteLine("Your number {0} is between 11 and 20.", myInt);
}
else if (myInt > 20 && myInt <= 30) {
Console.WriteLine("Your number {0} is between 21 and 30.", myInt);
}
else {
Console.WriteLine("Your number {0} is greater than 30.", myInt);
}
}
}

说明



1.清单3-1中的IF语句的各种格式都使用了同一个输入变量"myInt"。

这是从用户获得交互内容的另一种方式。我们首先输出一行信息:"Please enter a number:"到控制台。"Console.ReadLine()"语句使得程序等待来自用户的输入,一旦用户输入一个数字,按回车键之后,该数字以字符串的形式返回到"myInput"变量中,由于我们需要的是一个整数,所以需要转换变量"myInput"成整型数据。用命令"Int32.Parse(myInput)"即可完成。 (Int32 等数据类型将在后面的课程中加以介绍。) 转换结果放到"myInt"变量中,这是个整数类型。2.有了我们所需要的类型的数据,就可以用"if"语句来进行条件判断了。

对于第一种形式的IF语句,格式为: if (boolean expression) { statements }。该语句必须以关键字"if"开始。之后,括号中为布尔表达式。该布尔表达式必须计算出一个true或者false值。在本例中,我们检查用户的输入,看看输入值是否大于0,如果表达式运算结果为true,就执行大括号中的语句。(我们把大括号之间的语句部分称为"block"。) 块中有一个或者多个语句。如果布尔表达式的值为false,我们就忽略块中的语句,直接执行块后面的语句。

3.除了没有块之外,第二种"if"语句的格式非常类似于第一种。

因此,如果布尔表达式为true,将会执行布尔表达式之后的第一条语句。当布尔表达式的值为false,布尔表达式之后的第一条语句将被忽略掉,而直接执行其后的程序语句。如果你只有一条语句需要执行,就用该格式的"if"语句。如果你打算在布尔表达式的值为true时,执行两条或者两条以上的语句,就必须把它们放到块中。我个人的建议是:无论需要执行几条语句,要养成把if语句放到块中的习惯, 这就使得你避免犯如下错误:当添加了一条语句之后,忘记了添加一对括号。

4.大多数时候,你需要作出如下选择:当条件满足时做一件事,否则做另外一件事。

清单3-1中,程序演示了这种if语句格式的用法。 当布尔表达式为true时, 就立刻执行"if"后面的那条语句, 而当布尔表达式为false时,就执行"else"关键字后面的语句。

5.当要计算多个布尔表达式时,你可以使用if/else if/else 这种格式,上面的例子程序演示了这种形式,从关键字"if"开始, 一旦布尔表达式为真,就执行if后面的块。但是,这一次,在组合关键字"else if"后面还可以进行多个条件的判断。"else if"语句后面也有个布尔表达式,一旦该布尔表达式的值为true,就会执行紧接其后的块。这种情形可以一直持续下去,直到所有的情况都已经计算出来,但是整个"if/else if"序列必须以"else"结束。当所有的"if"或者"else if" 后面的布尔表达式的值都为false时,就执行关键字"else"后面的块。 对于if/else if/else格式的语句,每次仅仅执行一个其中部分的语句 。

6.上面的例子中,布尔表达式 (myInt < 0 || myInt == 0)包含了条件OR (||)运算符。

对于常规OR (|)运算符和条件OR (||)运算符来说,只要有运算符两边的子表达式之一为真,整个布尔表达式的值就为真。两个运算符的区别在于:正规OR 运算符(|)每次都对运算符(|)两边的表达式进行计算。而条件运算符OR (||)只有当第一个子表达式的值为false时,才计算第二个子表达式的值。

7.布尔表达式 (myInt > 0 && myInt <= 10)包含了条件运算符AND。

对于常规AND (&) 运算符和条件AND (&&)运算符来说,只有当运算符两边的子表达式的值都为真时,整个布尔表达式的值为真。两种运算符的区别在于:正规AND (&)运算符每次都计算运算符两边的子表达式的值,但是对于条件AND运算符来说,只有当第一个子表达式的值为真时,才计算第二个表达式的值。条件运算符(&& 和 ||) 通常称为运算优化的运算符,因为有时不需要计算整个表达式的值。这样就可以忽略掉不必要的逻辑表达式的计算,可以生成有效的代码。

同if/else if/else 格式的"if"语句类似,"switch"语句的用法如下:
2.清单3-2. 分支选择语句: SwitchSelection.cs

using System;
class SwitchSelect {
public static void Main() {
string myInput;
int myInt;

begin:
Console.Write("Please enter a number between 1 and 3: ");
myInput = Console.ReadLine();
myInt = Int32.Parse(myInput);
// switch with integer type
switch (myInt) {
case 1:
Console.WriteLine("Your number is {0}.", myInt);
break;
case 2:
Console.WriteLine("Your number is {0}.", myInt);
break;
case 3:
Console.WriteLine("Your number is {0}.", myInt);
break;
default:
Console.WriteLine("Your number {0} is not between 1 and 3.", myInt);
}

decide:
Console.Write("Type \"continue\" to go on or \"quit\" to stop: ");
myInput = Console.ReadLine();
// switch with string type
switch (myInput) {
case "continue":
goto begin;
case "quit":
Console.WriteLine("Bye.");
break;
default:
Console.WriteLine("Your input {0} is incorrect.", myInput);
goto decide;
}
}
}

说明

1.清单3-2 演示了多分支选择语句switch的用法。

关键字"switch"后面是switch 表达式。Switch表达式必须是以下类型中的一种: sbyte,byte,short,ushort, int,uint,long,ulong,char,string,或者enum类型。(enum类型将在后面的课程中加以介绍)。在清单3-2的第一个"switch"语句中, switch 表达式计算的是整数类型的数据。

2.在switch表达式后面是个switch 块, 当Switch表达式的值同某一个case后面的常量表达式的值相匹配时,就执行此case后面的语句,直到遇到"break"语句或者"goto"语句为止。每个分支以关键字"case"作为标号,其后为常量表达式,然后是分号(:)。本例子程序中,我们有"case 1:","case 2:"和"case 3:"。

3.你可以在所有的分支选择的后面加上一个"default"分支。

如果没有匹配的常量表达式,就进入default分支,并执行该分支的语句。虽然default标号是可选的,我建议你加上该分支。这将有助于处理一些意外事件 ,使得你的程序能够捕捉和处理不可预见的事件,从而使得程序更加可靠。

4.每个"case"标号必须以"break"语句作为结束。

"break"语句将使得程序退出switch语句,并从switch块后面的一条语句开始执行。对于"default"标号来说,"break"语句是可选的,因为有"break"语句和没有"break"语句,其运行结果是一样的。如果你在switch块中放置了一个"goto"语句,情况就不一样了。

5.清单3-2中的第二个"switch"语句演示了"goto"语句的用法。

"goto"语句可以让程序跳到关键字"goto"后面的标号中去执行。程序执行过程中,如果用户打入"continue", switch语句就匹配case "continue" 中的常量表达式,并执行"goto begin:"语句。程序就会离开"switch"语句,开始执行标号"begin:"后的第一条语句。这是个有效的循环,可以让你多次重复执行同样一段代码。一旦用户打入字符串"quit",循环将会结束。此时,将进入case "quit" 分支。该分支将输出信息"Bye."到控制台上,之后跳出switch语句,再结束程序。

一旦输入的字符串既不是"continue"也不是"quit",就会进入"default:"分支。于是,将会输出一个出错信息到控制台上,之后执行"goto decide:"命令。这就使得程序转跳到"decide:" 标号后面的第一条语句, 该语句执行后,将会询问用户是否愿意continue(继续)还是 quit(退出)。这是个有效的循环。

显然,"goto"语句功能强大,在受控的场合下,"goto"语句是很有用途的。但是,必须指出的是,"goto"如果出现被滥用的趋势,程序的调试和维护将会变得很困难。想象一下,如果程序到处可见goto语句,其流程将会变得难以阅读和理解。下节课中,将介绍在程序中创建循环语句的更好方法。


Thinking in life, thinking in love, thinking in dream,thinking in you !
月光倾泻,岁月沉沦
[url=http://58189.]http://58189.[/url]
2007-12-12 13:51
燃燒
Rank: 9Rank: 9Rank: 9
来 自:磁盘驱动器
等 级:贵宾
威 望:56
帖 子:9878
专家分:2
注 册:2006-4-20
得分:0 
C#方法
以往,对于每个程序来说,所有的工作都在Main()方法中实现。这对于功能简单的程序是合适的,因为仅仅用来学习一些概念。有个更好的方法来组织你的程序,那就是使用方法。方法是很有用的,因为方法可以让你在不同的单元中分开设计你的逻辑模块。

方法的结构格式如下:

属性 修饰符 返回值类型 方法名(参数) { 语句 }

我们将在后面的课程中,讨论属性和修饰符。方法的返回值可以是任何一种C#的数据类型,该返回值可以赋给变量,以便在程序的后面部分使用。方法名是唯一,可以被程序调用。为使得你的代码变得更容易理解和记忆,方法的取名可以同所要进行的操作联系起来。你可以传递数据给方法,也可以从方法中返回数据。它们由大括号包围起来。大括号中的语句实现了方法的功能。

1.清单5-1. 一个简单的方法: OneMethod.cs

using System;
class OneMethod {
public static void Main() {
string myChoice;
OneMethod om = new OneMethod();

do {
myChoice = om.getChoice();
// Make a decision based on the user's choice
switch(myChoice) {
case "A":
case "a":
Console.WriteLine("You wish to add an address.");
break;
case "D":
case "d":
Console.WriteLine("You wish to delete an address.");
break;
case "M":
case "m":
Console.WriteLine("You wish to modify an address.");
break;
case "V":
case "v":
Console.WriteLine("You wish to view the address list.");
break;
case "Q":
case "q":
Console.WriteLine("Bye.");
break;
default:
Console.WriteLine("{0} is not a valid choice", myChoice);
}

// Pause to allow the user to see the results
Console.Write("Press any key to continue...");
Console.ReadLine();
Console.WriteLine();
} while (myChoice != "Q" && myChoice != "q"); // Keep going until the user wants to quit
}

string getChoice() {
string myChoice;
// Print A Menu
Console.WriteLine("My Address Book\n");
Console.WriteLine("A - Add New Address");
Console.WriteLine("D - Delete Address");
Console.WriteLine("M - Modify Address");
Console.WriteLine("V - View Addresses");
Console.WriteLine("Q - Quit\n");
Console.WriteLine("Choice (A,D,M,V,or Q): ");

// Retrieve the user's choice
myChoice = Console.ReadLine();
return myChoice;
}
}

说明



1.清单5-1中的程序类似于第四课中的DoLoop程序。

区别在于:前一课中的程序打印出菜单内容,并在Main()方法中接受用户的输入,而本课中,该功能用一个名为getChoice()的方法实现,该方法的返回值类型是个字符串类型。在main方法中,在switch语句中用到了该串。方法"getChoice"实现了调用时所完成的工作。方法名后面的括号内是空的,因为调用getChoice()方法时,不需要传递任何数据。2.在方法块中,我们首先定义了变量"myChoice"。

虽然它与 Main()方法中的"myChoice"变量同名同类型, 但它们是不同的两个变量,因为局部变量仅仅在其定义的块内可见。换句话说, getChoice()方法中的"myChoice" 同Main()方法中的"myChoice"变量没有丝毫联系。getChoice()方法打印出一个菜单到控制台,并读取用户的输入。"return" 语句把"myChoice"变量值返回给Main()方法中的调用者getChoice()。注意: "return"语句返回类型同该方法中定义的返回值类型相同,本例中,该返回值是个字符串。

3.在Main()方法中,在使用getChoice()之前,实例化了一个新的"OneMethod"对象。

这是因为:我们没有指明一个"静态"修饰符。(注意:Main()函数带有"静态"修饰符),getChoice()就成为一个实例的方法。 实例方法和静态方法的区别是:前者可以创建多个类的实例,每个实例有自己的单独的getChoice()方法。而一旦方法是静态的,就不存在方法的实例,你只能调用该静态方法的一个实现。

所以,正如前面所讲的,因为getChoice()并不是静态的,所以,我们必须实例化一个新对象来使用它。这是通过定义"OneMethod om = new OneMethod()"来进行的。在等号的左边,是对象引用"om",其类型是OneMethod。"om"是个对象的引用,这点很重要,"om"并不是对象自身,它是个引用OneMethod类型对象的变量。 在等号的右边,把新创建的OneMethod对象赋给引用"om"。 关键字"new"是个在堆上创建对象的新实例的C#运算符。此处完成的工作是: 在堆上创建一个新的OneMethod实例,并把它赋给om引用。一旦有了om引用的OneMethod对象实例,就可以通过om引用来对实例进行处理。

方法,域和其他类成员可以通过"." (点)运算符进行访问,标识和操纵。一旦需要调用方法getChoice(),就通过om引用,并使用点运算符"om.getChoice()"来进行。 getChoice() 块中的语句执行完毕之后即返回。为了捕捉到getChoice()的返回值,我们使用了赋值运算符"="。 返回串放到了Main()函数的局部变量 myChoice中,从那里,程序的其余部分按照前面课程中介绍的方式正常执行。

2.清单5-2. 方法参数:MethodParams.cs

using System;
class Address {
public string name;
public string address;
}
class MethodParams {

public static void Main() {
string myChoice;
MethodParams mp = new MethodParams();
do {
// show menu and get input from user
myChoice = mp.getChoice();
// Make a decision based on the user's choice
mp.makeDecision(myChoice);
// Pause to allow the user to see the results
Console.Write("Press any key to continue...");
Console.ReadLine();
Console.WriteLine();
} while (myChoice != "Q" && myChoice != "q"); // Keep going until the user wants to quit
}

// show menu and get user's choice
string getChoice() {
string myChoice;
// Print A Menu
Console.WriteLine("My Address Book\n");
Console.WriteLine("A - Add New Address");
Console.WriteLine("D - Delete Address");
Console.WriteLine("M - Modify Address");
Console.WriteLine("V - View Addresses");
Console.WriteLine("Q - Quit\n");
Console.WriteLine("Choice (A,D,M,V,or Q): ");
// Retrieve the user's choice
myChoice = Console.ReadLine();
return myChoice;
}

// make decision
void makeDecision(string myChoice) {
Address addr = new Address();
switch(myChoice) {
case "A":
case "a":
addr.name = "Joe";
addr.address = "C# Station";
this.addAddress(ref addr);
break;
case "D":
case "d":
addr.name = "Robert";
this.deleteAddress(addr.name);
break;
case "M":
case "m":
addr.name = "Matt";
this.modifyAddress(out addr);
Console.WriteLine("Name is now {0}.", addr.name);
break;
case "V":
case "v":
this.viewAddresses("Cheryl", "Joe", "Matt", "Robert");
break;
case "Q":
case "q":
Console.WriteLine("Bye.");
break;
default:
Console.WriteLine("{0} is not a valid choice", myChoice);
}
}

// insert an address
void addAddress(ref Address addr) {
Console.WriteLine("Name: {0}, Address: {1} added.", addr.name, addr.address);
}
// remove an address
void deleteAddress(string name) {
Console.WriteLine("You wish to delete {0}'s address.", name);
}
// change an address
void modifyAddress(out Address addr) {
//Console.WriteLine("Name: {0}.", addr.name); // causes error!
addr = new Address();
addr.name = "Joe";
addr.address = "C# Station";
}
// show addresses
void viewAddresses(params string[] names) {
foreach (string name in names) {
Console.WriteLine("Name: {0}", name);
}
}
}

说明



1.清单5-2是清单5-1的修改,主要是对程序进行了模块化,并添加了更多的实现,以便阐述参数传递的用法。

C#可以处理四种类型的参数:out(输出),ref(引用),params(数组)和value(值)。为了说明参数的用法,我们用两个字符串域创建地址类。2.在Main()方法中,我们调用getChoice()来读取用户的输入,并且把字符串放到myChoice变量中。

之后,把myChoice变量作为makeDecision()函数的实在参数。在实现makeDecision()方法时,注意其形式参数为字符串myChoice。需要再次说明的是:这是个新的myChoice变量,不同于调用者的实在参数,仅仅是适用于本方法的局部变量。 因为makeDecision()方法的myChoice参数没有任何其他修饰符,故认为它是"值"参,即实在参数的值被拷贝到栈中,故作为值参的变量是局部的,任何对局部变量值的改变并不影响到调用者的实在参数的值。换句话说,值参仅仅是来自调用者的输入。

3.makeDecision()方法中的switch语句完成如下功能:

在每种情形下,都调用相应的方法。这些方法的调用不同于Main()方法。除了使用"mp" 引用,它们还使用了"this"关键字。"this"是对当前对象的引用。由于makeDecision()方法不是静态方法,当前对象已经被实例化,所以可以使用"this"引用来调用同一实例中的方法。

4.addAddress()方法用到了"ref"参数,即引用可作为参数来传递,即该引用被拷贝到栈中,其引用的对象同调用者的实参所引用的对象是同一个。

这意味着:任何对局部引用的对象的改变也就是对调用者所引用的对象的改变。你可以想象一下,这就相当于输入/输出参数。

5.modifyAddress()中有一个输出参数。

输出参数仅仅传递给被调用函数。一旦调用该方法时,在栈中的仅有的一个引用未被赋值,因为根据赋值的确定性原则,在该变量没有被赋值之前,就不能使用该变量。modifyAddress()方法的第一行作为注释,说明了这一点。你可以试着去掉注释符,编译一下程序,看看结果如何。一旦该变量被赋了值,在程序返回之后,输出参数就被拷贝到调用者的参数中。所以,在方法返回之前,必须给输出参数赋值。

Thinking in life, thinking in love, thinking in dream,thinking in you !
月光倾泻,岁月沉沦
[url=http://58189.]http://58189.[/url]
2007-12-12 13:54



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-191757-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.144548 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved