



版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Microsoft公司.c#介绍C#是ー种简单、先进、面向对象和类型安全的编程语言,由C和C++派生而来。C#(读作"Csh即’)深深地根植于C和C++语言家族。C和C++的编程人员能够很快熟悉它。C#的目标是将VisualBasic的高效率和C++的强大功能相结合。2000年6月20日©Microsoft公司版权,1994200〇.版权所有.C#介绍〇・是一种简单、先进、面向对象和类型安全的编程语言,由c和C++派生而来。c#(读作“Csharp")深深地根植于C和C++语言家族。C和C++的编程人员能够很快熟悉它。C#的目标是将VisualBasic的高效率和C++的强大功能相结合。C#是MicrosoftVisualStudio7.0的ー个组成部分。除了¢#外,VisualStudio还支持VisualBasic,VisualC++,和脚本语言VBScript和Jscript.所有这旳语言都可以应用Microsoft.NET平台,该平台包括ー个通用执行リI擎(8mmonexecutionengine)和一个丰富的类库。Microsoft.NET平台定义了一个"通用语言子集CommonLanguageSubset"(CLS),这是ー种混和的语言,确保了CLS语言和类库之间可以无缝地交互工作。对于C#开发人员而言,这意味着尽管C#是利新的语言,它完全可以使用经验丰富的开发工具VisualBasic和VisualC++所使用的多个类库。C#本身不包括任何类库。本文描述该语言的ー些重要特点,但并不是完整的语言说明。目的是向读者介绍该语言,以便于开发最初的程序和阅读完整的语言Hello,world程序经典的“Hello,world"程序可以按照如下方式编写:usingSystem;classHe1I〇IstaticvoidMain()(Console.做iteLine("Hello,worid");C#程序的源代码通常保存在ー个或多个扩展名为.cS的text文件中,例如he11。.cS。利用VisualStudio提供的命令行编译器,利用ド面的命令编译该程序:esche11o.cs结果生成了一个名为hello.exe的文件。这个程序的运行结果是Hei1〇,worId该程序详细分析如下:"usingSystem;”直接指向ー个Microsoft.NET类库支持的名为sysIem的命名空间•该命名空间包含在岫in方法中指向的控制台类。命名空间提供了结构化的方法来组织ー个类库的各个元素。“using”命令表示可以无限制地使用命名空间地各种类型。在“Hello,world”程序中Console.卅iteLine是System.Console.WiteLine的缩写。岫in方法是类Hello的ー个元素。它冇ー个静态标识符,表示它是类Hello的ー个方法而不是一个例程。»一个程序的主要入口一所谓的开始执行的方法一是ー个名为Main的静态方法。输出“Hell。,world”是通过由一个类库产生的。本语言自身并不提供类库。相反,它使用了VisualBasic和VisualC++所使用的通用类库。C和C++开发人员会对"Hello,world”程序中没有出现的ー些元素感兴趣:该程序并没有在Main中使用全局方法。没有全局的方法和变量;这些元素总是包括在类型声明中(如类和结构的声明)。程序也没有使用“::”或操作符。“::”不再是ー个操作符,并且“ー〉”操作符只在很少一部分程序中使用。“.”操作符在例如Cons01e.WiteLine的复合名中使用。程序没有先声明。先声明不再需要,因为声明的顺序不再重要。程序没有使用#来包含导入程序。程序间的独立性只是象征性的而不是严格的。系统消除了使用不同语言编写的程序之间的障碍。例如,Console类可以用另外的语言编写。类型C#支持两种类型:value类型和referens类型。Value类型包括简单类型(如:char,int和float)、enum类型和struct类型。Reference类型包括class类型、interface类型、delegate突型和array类型。Value类型和reference类型的不同之处在于value类型的变量直接存储它们的数据,然而reference类型的变量存储对象的指针。Reference类型使得两个变量可以指向同一个对象,因此对ー个变量的操作可能会影响到多个变量指向的对象。对「value类型,每个变量有它们自己的数据拷贝,因此对ー个变量的操作不会影响到其他变量的值。例子:usingSystem;classClass1IpublicintVa1ue=0;)classTest(staticvoidMain(){ntvI=0;ntv2=v1;v2=123;Class1r1=newClass1();Class1r2=r1;r2.Vaiue=123;Console.卅iteLine("VaIues:{0|,(1|*,vI,v2);Console.的iteLine("Refs:{0),|1|",r1,Vaiue,r2,Va1ue);I)显示了它们的区别。程序的输出为:Vaiues:0,123Refs:123,123局部变量V1的赋值并没有影响到局部变量V2的值,因为这两个局部变量都是value类型(int类型),并且每个value类型的局部变量都有自己的存储空间。相反,r2.Value=123;的赋值语句同时改变了rI和r2所指向的对象。程序行Console.WriteLine("Vaiues:(0),(1|",vl,v2);Console.W'iteLine("Refs:(01,{1)",r1.Va1ue,r2.Vaiue);需要进ー步讨论,因为它们使用了Console.MiteLine的字符串格式,它实际上有多个参数。第一个参数是ー个字符串,可能包含类似于{0}和“}的按数字顺序排列的占位符。每个占位符指向ー个示踪参数。占位符{0}指向第二个参数,占位符{1}指向第三个参数…。在输出发送到控制台之前,占位符被它们相应的参数所替换。开发人员可以通过enum和struct声明定义新的value类型,也可以通过class,interface和delegate定义新的reference类型。例子:usingSystem;publicenumCoIorIRed,Blue,Green1publicstructPointIpublicintx,y;)publicinterface(BaseIvoidF();)publicinterfaceIDerived:(BaseIvoidG();)publicclassAIprotectedvoidH()(Console.WiteLine(HA.H");)1publicclassB:A.1DerivedIpublicvoidF()|Console.W'iteLine("B.F,impIementationofIDerived.F");IpublicvoidG()(Console.的iteLine("B.G.impIementationof【Derived.G");)overrideprotectedvoidH()(Console.\WiteLine("B.H,overrideofA.H");I)publicdelegatevoidEmptyDeIegate();列举了每种类型的ー个或两个声明。后面还将详细描述类型声明。预定义频C#提供了预定义类型的集合,CandC++开发人员将对它们屮的大部分非常熟悉。预定义reference类型有対象和字符串。对象类型是其他所有类型的最基础类型,字符串类型用来表示统编码的字符串值。预定义value类型包括有符号和无符号整数类型、浮点类型以及b。。1、char和decima1类型。有符号整数类型有sbyte、short、int和long:无符号整数类型有byte、ushort、uint和dulong;浮点类型有float和double。sbool类型一般用ア表示布尔数值:值为true或false。Bool类型便「编写自我说明的代码,也有助于消除C++程序编写中的一个普遍性错误,即开发人员在应该使用“==”的地方错误地使用“ゴ。在C#中,例子inti=...;F(i);if(i=0) //Bug:thetestshou1dbe(i==0)G();
是不正确的,因为表达式i=〇是int类型的,而程序中需要的是bool类型的表达式。Char类型一般用于表示统编码的字符。ー个char类型的变量表示ー个16位统・编码的字符。Decima!类型适用于不能有舍入误差的计算。常见的例子包括金融结算比如税收估计和流通货币转换。Decima!类型有28位有效数字。卜表列出了预定义类型,并显示如何赋值。类型描述例子object是所有其他类型的基础类型objecto=null;string字符串类型;ー个字符串是ー个统ー编码的字符序列strings=*'He11o";sbyte8位有符号整数类型sbyteva1=12;short16位有符号整数类型shortva1=12;int32位有符号整数类型intva1=12;long64位有符号整数类型1ongval1=12;longva12=34L;byte8位无符号整数类型bylevail=12;byteva12=34U;ushort16位无符号整数类型ushortvail=12;ushortva12=34U;uint32位无符号整数类型uintvail=12;uiniva12=34U;uiong64位无符号整数类型ulongvail=12;ulongva12=34U;alongva13=56L;alongva14=78UL;float单精度浮点类型floatva1=1.23F;double双精度浮点类型doublevail=1.23;doubleva12=4.56D;bool布尔类型;ー个布尔类型的值为true或falseboolvail=true;boolva12=fa1se;char字符类型;ー个char的值是ー个统・编码的字符charva1='h*;decima1有28位有效数字的精确十进制类型decima1val=1.23M每个预定义类型是ー个系统定义类型的缩写。例如关键字int是一个名为System.Int32的struct的缩写。这两个名字可以交换使用,一般来说最好使用关键字而不是使用完整的系统类型名。预定义value类型比如int冇多种特殊处理方法,在大部分情况下和其他structsー样。操作符重载使得开发人员可以定义类似于预定义类型的变量。例如,一个Digitstruct可和预定义整数类型・样支持系统的数学运算,并且可以定义Digit和预定义类型之间的转换。预定义类型本身具有操作符重载性。例如,比较操作符==和!=对于不同的预定义类型有不同的含义。»两个int类型的表达式如果它们代表的相同的整数值,则认为它们相等。»两个。bject类型的表达式如果指向相同的对象,或两者都为null,则认为它们相等。.两个string类型的表达式如果字符串的长度相等并且对应的位置上字符相同,或两者都为null,则认为它们相等。例子classFeststaticvoidMain()(string$="Test";stringt=string.Copy(s);Console.iteLine(s==t);Console.WiteLine((object)s==(object)t);)1生成如下的输出TrueFalse因为第一个比较的是两个siring类型的表达式,第二个比较的是两个。bject类型的表达式。转换有两种类型的转换:模糊转换和精确转换。模糊转换用于那些不需要仔细审査也可安全运行的转换。例如,从int类型到long类型的转换就是ー个模糊转换。这个转换总是成功的,也不会导致信息的丢失。模糊转换可以不精确执行,如下面的例子usingSystem;classTestIstaticvoidMain()(intintVa1ue=123;longIongVaIue=intVaIue;Console.W,iteLine(w(long){0)=(1|",intVaIue,IongVa1ue);)1不精确地从int转换成|ong0相反,精确转换有大量表达式执行。例子usingSystem;classFest(staticvoidMain()(longIongVa1ue=Int64,MaxVa1ue;intintVa1ue=(int)1ongVa1ue;Console.WiteLine("(int){0|=(1|,IongVaIue,intVa1ue);)1利用ー个精确转换来将一个long转换为ー个int。输出为:(int)9223372036854775807=-1因为产生了溢出。Array类型数组可以是・维或多维。支持规则“rectangular”数组和不规则“jagged”数组。ー维数组是最常见的类型,也是ー个很好的出发点。例子usingSystem;classTest(staticvoidMain()(TOC\o"1-5"\h\zint[]arr=new i nt[ 5];for(int i = 0; i < arr. Length; i++)arr[i] = i *i ;for(int i = 0; i < arr. Length; i++)Console.\WiteLine("arr[(0)]=(1ド,i,arr[i]);创建了一个int类型的ー维数组,初始化该数组元素,然后将它们打印出来。程序的输出为:arr[0]=0arr[1]=1arr[2]=4arr[3]=9arr[4]=16前面例子中的类型int[]是一个数组类型。数组类型有一个非数组类型以及紧跟其的ー个和多个维度说明构成。例子classTestIstaticvoidMain()(int[]al; //int类型的ー维数组int[,]a2; IIint类型的二维数组int[,,]a3; IIint类型的三维数组intl]|]j2; I!不规则数组:数组(int数组)int[][][]j3; //数组(数组(int数组)))显示了多个局部变量的声明,它们都使用int数组类型作为元素类型。数组是reference类型的,因此ー个数组变量的声明仅仅留出了一个指向数据的地址空间。数组例程实际上通过数组初始化和数组创建表达式创建。例子classTeslstaticvoidMain()(int[)a1=newint[](1,2,3);int[,]a2=newint[.|({I,2,3},(4,5,6)};intj.,]a3=newint[10,20,30];TOC\o"1-5"\h\zint[IIJ j2=new i nt ( 3][];j2[0] = new int[ ] ( 1. 2, 3);j2[I] = new int[ ] | 1, 2, 3, 4, 5, 6);j2[2] = new int( ] ( 1, 2, 3, 4, 5, 6,7,8,9};ー些数组创建表达式。变量al、a2和a3表示规则数组,变量j2表示一个不规则数组。这些术语是建立在数组形状的基础上的。规则数组总是有一个规则形状。给定数组各个维度的大小,它的规则现状就很清楚。例如,a3三个维度大小分别为10、20和30,可以很清楚地看出这个数组包含10*20*30个元素。相反,变量j2表示一个不规则数组,和一个“数组的数组”。更确切的说是,j2表示ー个int数组的数组,和一个一维int”类型的数组。每个in“]变量可以単独初始化,这就使得数组有一个不规则的形状。本例子中每个int数组有不同的长度。更确切的说是,j2[0]的长度为3,j2[l]的长度为6,j2[2]的长度为9。元素的类型和维度大小是数组类型的一部分,但每个维度的长度不是数组类型的部分。这个区别在语言语法中是很清楚的,因为每个维度的长度是在数组创建表达式而不是在数组类型中指定的。例如声明in(1,,]a3=newint[10,20,30];有一个数组类型int[,,]和一个数组创建表达式newint[10,20,30]〇对于局部变量和区域声明,允许有缩写形式,因此没有必要再写ー次数组类型。比如例int[]a1=newint[]{1,2,3);可以缩写成intI]al=(1,2,3);在程序语义单是没冇任何区别的。数组初始化例如”,2,3)的上下文用于决定被初始化的数组类型。例子classTestIstaticvoidMain()(short[]a={1,2,3};int[]b={I,2,3(;1ong[]c={1,2,31;)1显示了系统的数组初始化可以应用」:几个不同的数组类型。因为需要一个上卜文来决定数组初始化的类型,因此在ー个表达式上下文中只使用一个数组初始化是不可能的。类型系^^一TypesystemunificationC#提供了一个“统ー类型系统”。所有的类型ー包括value类型一由。bject类型派生而来。对于任何值,即使是简单类型例如int的值,都可以调用object方法。例子usingSystem;classTestIstaticvoidMain()(Console.W-iteLine(3.ToString());I)在ー个整数中调用对象定义ToString方法。例子classTeststaticvoidMain(){inti=123;objecto=i; //boxingintj=(int)o;//unboxingI(更冇趣。ー个int数值可以转化成对象,然后再转化为int。这个例子显示了box/hg和unboxing-当ー个value类型的变量需要转化为reference类型,将分配ー个对象盒box来保存这个值,然后这个值被拷贝到box中。L/raboxMg刚好相反。当ー个对象盒变成它的初始value类型,这个数值从box中拷贝出来,并放置到相应的存储地址中。类型系统统・使得value类型具有对象的优势,这并不需要不不必要的花费。对于不需要int数值具冇对象功能的程序来说,int数值仅仅是32位数值而已。对于需耍int数值具有对象功能的程序来说,这种能力刚好可以满足需要。这种将value类型作为对象处理的能力连接了value类型和reference类型之间的差别,多数语言中均存在这种差别。例如,一个Stack类可以提供Push和Pop方法来返回对象值。publicclassStackIpublicobjectPop()(...)publicvoidPush(objecto){...|)因为C#有一个统ー类型系统,这个Stack类可以作为任何类型的堆栈使用,包括value类型如int»变量:和参数parameter变簸示ー个存储空间。每个变量都有其类型,类型决定了什么样的值可以存储在该变量中。局部变量是那些在方法、属性或索弓I中声明的变量。ー个局部变量通常冇ー个类型名称,并且有一个说明符来指定变量名称和初始值,如下所示:inta;intb=1;一个局部变量的声明中也可以包括多个说明符。说明符a和b可以书写如下:inta,b=1;在对・个变量的值进行运算之前,必须对该变量进行赋值。例子classrest(staticvoidMain()(inta;intb=1;intc=a+b;1…1是不正确的,因为它试图在变量赋值之前对其进行操作。尼必是一个变量,它和类或struct(或它们的实例)相关。ー个field声明如果包括static修饰符,则其被定义位一个静态变量,否则为ー个/わstance变曷。例子usingSystem.Data;classEmpIoyee(privatestaticDataSetds;publicstringName;pub1icdecima1Salary;)中有一个Employee类,其中包括一个私冇静态变量和两个公冇例程变量。正式的参数声明过程也可以定义变量。有四种类型的参数:value参数、reference参数、output参数和params参数。心/ue参数用于“in”参数传递中,用于将一个变量的值传递到方法中,并且参数值的改变不会影响到初始变量值。Value参数指向它自己的存储地址,和其对应的变量存储地址是分开的。该存储地址在拷贝对应变量值的时候进行初始化。例子usingSystem;classTesl(staticvoidF(intp)(Console.WiteLine(Np=(。ド,p);P++;IstaticvoidMain()(inta=1;Console.W-iteLine(Mpre:a=(0)",a);F(a);Console.^iteLine("post:a={0)",a);)1有一个方法F,它包括ー个名为p的value参数。该例子输出结果为:pre:a=1p=Ipost:a=1参数的值被改变了。Reference参数用于‘byreference"参数的传递,在其中参数的作用是充当调用参数的别名。Reference参数本身没有一个存储地址,但它指向一个相应变量的存储地址。修改ー个reference参数会立即影响相应的变量:。ー个reference参数用ref修饰符来声明,例子usingSystem;classTest(staticvoidSwap(refinta,refintb)(intt=a;a=b;b=i;staticvoidMain()(ntx=1;nty=2;Console.WiteLine("pre:x=(01,y=(1)",x,y);Swap(refx,refy);Console,^iteLine("post:x=(0),y=(1|",x,y);I1有一个Swap方法,其中冇两个reference参数。程序的输出为:pre:x=l,y=2post:x=2,y=1ref关键字在正式参数声明和使用中是必需的。在调用处使用ref可以引起开发人员对该参数的注意,使得开发人员知道调用的结果可以改变参数的值。Output参数类似于reference参数,只是调用提供的调用者参数的初始值不再重要。output参数的声明包括ー个out修饰符。例子usingSystem;classTest(staticvoidDivide(inta,intb,outintans,outintrem)(ans=a/b;rem=a%b;)staticvoidMain()(for(inti=1;i<10;i++)for(intj=I;j<10;j++)(intans,r;Divide(i,j,outans,outr);Console.WiteLine("{0);(1)={2}r{3ド,i,j,ans,r);)))中采用了Divide方法,包括两个output参数一ー个用于除方法的结果,另一一个用于余数。对于value、reference-flioutput参数而言,调用变量提供的调用者变量和表示它们的参数是对应的。params参数允许多对ー:单个params参数可以表示多个变量。换句话说,params参数允许多个变量集合。Params参数的声明包括params修饰符。给定一个方法,只能冇ー个params参数,并且需要在最后指定该参数。params参数的类型是ーー维数组类型。ー个调用函数可以传递单个这种数组类型的变量,也可以传递多个这种变量。例如下面的例子usingSystem;classTest(staticvoidF(paramsintI]args)(Console,WeiteLine("#ofarguments:<0)",args.Length);for(inti=0;i<args.Length;i++)Console.WiteLine(H\targs|10|j={1)H,i,args[i]);)staticvoidMain(){F(1,2);F(1,2,3);F(newint[]{1,2,3,4));I1中有一个方法F,具有多个int变量,例子多次调用了该方法,输入为:〇farguments:0ofarguments:1args[0]=Iofarguments:2args(01=1args[1]=2ofarguments:3args[01=1args[1]=2args[2]=3ofarguments:4args[0]=1args[1j=2args[2]=3args[3]=4
本介绍的大部分例子都使用Console类的WiteLine方法。在该方法的变量替换,如下面的例子所示।fiIa=]I)-2'Console.WiIeLine(*'a=(0|,b={I)H,a,b);是通过ー个params参数实现的。WiteLine方法通常包含多个重载方法(可以传递少数的变量)加一个具有params参数的方法。namespaceSystemIpublicclassConsolepublic static void WriteLine(string s) {.. .|pub1ic static void WriteLine(string st obj ect a) (...|pub1ic static void WriteLine(string s, obj ect a, object b)pub)icstaticvoidpub)icstaticvoid卅iteLine(strings,paramsobject[]args)自动内存管理ナエ为存管理需要开发人员管理内存块的分配和回收。手工内存管理费时又费カ。自动内存管理的实现,将开发人员从这个繁重的任务中解放出来。在大多数情况下,自动内出管理提高了程序代码的质量和开发人员的开发效率,对编程和实现并没有什么不好影响。例子usingSystem;publicclassStackIprivateNodefirst=nul1;publicboolEmpty(get(return(first==null);))publicobjectPop()(if(first==nulI)thrownewException("Can'tPopfromanemptyStack.");else(objecttemp=first.VaIue;first=first.Next;returntemp;publicvoidPush(objecto){first=newNode(o,first);IclassNode{publicNodeNext;publicobjectValue;publicNode(objecivalue):this(vaIuetnull)()pubIicNode(objectvaIue,Nodenext)(Next=next;VaIue=va1ue;)有一个Stack类,通过相连的节点实例来实现。节点实例在Push方法中创建,不使用时再回收处理。当ー个节点实例不再被任何程序代码所调用时,就会被回收。例如,当从Stack中删除ー项时,相应的那个节点就可以被回收。例子classTestIstaticvoidMain()(Stacks=newStack();for(inti=0;i<10;i++)s.Push(i);s=nul1;是一个应用Stack类的测试程序。程序中创建了一个Stack,并初始化为10个元素,然后赋值为null。一旦变量赋值为nul1,Stack和相应的10个节点就可以被回收。回收处理机允许马上回收它们,只不过并不需要这样做。对于一般情况下对自动内存管理非常满意,有时候又需要精确控制或特殊的功能的开发人员来说,C#也提供了编写这种“不安全”代码的能力。这种代码可以通过指针类型来直接处理,并且利用以对象可以暂时阻止回收处理机工作。这种“不安全”代码特性从开发人员和使用人员的角度来说其实是“安全”的。不安全代码在程序中必须使用unsafe修饰符标识出来,以便开发人员正确使用这些不安全特性,并且编译器和执行器也会ー起保证这些不安全的代码不会化妆成安全代码。例子usingSystem;classTest(unsafestaticvoidW-iteLocations(byte[]arr)(fixed(byte*p_arr=arr)(byte♦p_e1em=p_arr;for(inti=0;i<arr.Length;i++)[bytevalue=*p_e1em;stringaddr=int.Format((int)pe1em,"X");Console.WriteLine("arr[{0)]at0x(1)is[2ド,i,addr,va1ue);pelem++;1'))staticvoidMain()(byte[]arr=newbyte|]{1,2,3,4,5);WiteLocations(arr);中应用了一个不安全的方法WiteLocations,固定了一个数组例程,并且使用指针对这些元素进行重复操作。每个数组元素的索引index、值value和地址输入到控制台中。程序的ー个可能输出结果为:arr[0]at0x8E0360is1arr[1jat0x8E0361is2arrI2]at0x8E0362is3arr[3]at0x8E0363is4arr[4]at0x8E0364is5当然,确切的内存地址是会变化的。表达式C#包括多个一元操作符符、多个二元操作符符和一个三元操作符符。下表列出了这些操作符,按照它们优先级的高低从上到下排列:类别操作符基本(x)x.yf(x)a[x]x++x--newtypeofsizeofcheckedunchecked一元+- ! 〜++x--x(T)x乘除*/%加减+一替换Shift<<>>关系Relational<><=>=is等于==!=逻辑与&逻辑或非XORA逻辑或1条件与&&条件或11条件?,赋值=*=/=%=+=-=<<=>>=&=A=1=当ー个表达式包含多个操作符时,操作符的优先级决定了先计算那个操作符。例如表达式x+y*z计算为x+(y*z)因为・操作符的优先级比+操作符高。当ー个操作符在两个优先级ー样的操作符中间出现时,操作符的关联性决定了该执行那个操作符。・除了赋值操作符之外,所有二元操作符是左关联的,意味着操作符是从左运算到右的。例如x+y+z计算为(x+y)+z.«赋值操作符和条件操作符(?:)都是右关联的,意味着操作符从右运算到左。例如x=y=z运算成x=(y=z)°优先级和关联性可以由括号来控制。例如,x+y*z首先计算y和z相乘,然后加上X。但(x+y)*z首先计算X和y的和,然后和z相乘。语句C#的大部分语句是从C和C++那里借用过来的,当然也冇ー些值得注意的增加和修改。下表列出了可以应用的语句种类,每种类别都有一个例
语句例子语句列表和块语句staticvoidMain()(F();GO;(H();1();)1标记语句和goto语句staticvoidMain(string)|args){if(args.Length==0)gotodone:Console.的iteLine(args.Length);done:Console.W-iteLine("Done");1局部常数语句staticvoidMain()|constfloatpi=3.14;constintr=123;Console.卅iteLine(pi*r*r);1局部变量语句staticvoidMain(){inta;intb=2»c=3;a=1;Console.WiteLine(a+b+c);1表达式语句staticintF(inta,intb){returna+b;1staticvoidMain()(F(1,2); //Expressionstatement1If语句staticvoidMain(string(]args){if(args.Length==0)Console,^iteLine("Noargs");elseConsole.MiteLine("Argsw);!一Swi1ch语句staticvoidMain(string[]args)(switch(args.Length)(case0:Console.WiteLine("Noargs");break;case1:Console.\WiteLine("Onearg");break;default:ntn=args.Length;Console,卅iteLine("(0)args",n);break;)1whi1e语句staticvoidMain(string)|args){inti=0;whi1e(i<args.1ength){Console.WiteLine(args[i]);i++;)1
Do语句staticvoidMain()strings;do|s=Console.whi1e(s!="Exit}{ReadLine();)");For语句staticvoidMain(stfor(inti=0;iConsole.的ileLi}ring||args)(<args.1ength;i++)ne(args|i]);Foreach语句staticvoidMain(stforeach(stringsCons〇!e.W"iteLi1ring[]args){inargs)ne(s);break语句staticvoidMain(stinti=0;whi1e(true)(if(i>argbreak;Console.Wi1)ring!1args)(s.Length)teLine(args|i++]);continue语RJstaticvoidMain(stinti=0;whi1e(true){Console1的iteLiif(i>args.Lecontinue;break;)1ring[|args){ne(args|i++]);ngth)return语句staticintF(inta,returna+b;)staticvoidMain()Console.MiteLinereturn;1intb)1((F(1,2));throw语句和try语句staticintF(inta,intb){if(b==0)thrownewException("Dividebyzero");returna/b;}staticvoidMain(){lry(Console.師iteLine(F(5,0));1catch(Exceptione)(Console,的iteLine("Error");11checked和uncheckedstaticvoidMain()intx=100000,y]=100000;Console.W1iteLineConsole.iteLineConsole•的ileLine}(unchecked(x*y));(checked(x*y));(x*y);lock语句staticvoidMain()Aa=...1ock(a)(a.P=a,P+1;I(类声明定义了一个新的reference类型。一个类可以继承其他的类,并且可以有零个或多个接口。类元素可以包括常数、域、方法、属性、索引、事件、操作符、构造函数、析构函数以及嵌套类型声明。每个元素有一个相关的访问性,决定了在那些程序文本空间内能够访问这个元素。总共有5种类型的访问性。如下表所示。形式含义public不受限制的访问protected程序内部或由所包含类派生的类型访问interna1本程序访问protectedinterna1程序内部或由所包含类派生的类型访问private所包含的类型访问usingSystem;classMyClassIpublicMyClass()(Console.MileLine("Constructor");)publicMyClass(in(va1ue)(MyField=va1ue;Console.MiteLine("Construc(or");I-MyClass()(Console.WileLine("Destructor");IpublicconstintMyConst=12;publicintMyFieId=34;publicvoidMyMethod(){Console.W-iteLine("MyCIass.MyMethod");IpublicintMyProperty(get(returnMyFieId;)set(MyFie1d=vaIue;)Ipublicintthis|intindex]{get(return0;
Console.師iteLine("thi$[{0}] {1}",index,va1ue);))pubIiceventEventHandlerMyEvent;publicstaticMyClassoperator+(MyClassa,MyClassb){returnnewMvClass(a.MyField+b.MyFie1d);)interna1classMyNestedCIass())中有一个类,包含了各种类型的元素。例子//Constan(usageConsole.W,iteLine("MyConst={〇}",MyClass.MyConst);//Fieldusagea.MyFieId++;Console.W-iteLine("a.MyField=<〇}二a,MyField);11Methodusagea.MyMethod();11Propertyusagea.MyProperty++;Console.teLine("a.MyProperty={0}",a.M>'Property);111ndexerusagea[3]=a[1]=a[2];Console.W-iteLine("a[3]=[。ド,a[3]);11Eventusagea.MyEvent+=newEventHandler(MyHand!er);11Over1oadedoperatorusageMyClassc=a+b;)staticvoidMyHandler(objectsender,EventArgse)(Console.MiteLine(**Test.MyHandler");)internaIclassMyNestedCIass0)显示了如何使用这些元素常数ー个常数是ー类表示一个不变值的元素:这个值可以在编译的时候就计算出来。在同一个程序中一个常数可以由另外一些常数计算得到,只要没有循环依靠就可以。例子classConstantsIpubIicconstintA=1;pubIicconstintB=A+I;)包括了一个名为Conslant$的类,其中有两个public常数。常数默认是静态的,可以由类访问,例如
classTestIstaticvoidMain(){Con$ole.WiteLine("(〇),{1)",Constants.A,Constants.B);)1显示了常数A和常数B的值。域Fields域的ズ是ー个元素,表示和对象或类相关的ー个变量。例子classColor(internaIushortredPart;internaIushortbluePart;internaIushortgreenPart;publicColor(ushortred,ushortblue,ushortgreen)(redPart=red;bluePart=blue;greenPart=green;)「ー显示了一个Color类,有名为redPart、greenPart和bluePart的内部例程域0域可以是静态的,如下面的例子newColor(OxFF,0,0);newColor(0.OxFF,0);=newColor(Ot0,OxFF);=newColor(0,0,0);有Red、BlueヽGreen和Wiite的静态域。静态域在这种情况下并没有很好地匹配。当Color类装载时,该域被初始化,但初始化后就没冇什么东西来阻止客户端对它们的改变。这种改变也许会在使用Color并且假定这些值不会变化的程序中带来不可预测的错误。只读域可以防止这个问题。ー个只读域的赋值只能在其声明中完成,或在相同类的创建过程中完成。这样Color类可以通过为静态域加入readonly修饰符来改进:classCoIoriniernaIushortredPart;internaIushortbluePart;iniernaIushortgreenPart;publicColor(ushortred,ushortblue,ushortgreen)(redPart=red;bluePart=blue;greenPart=green;d=newColor(OxFF,0,0);ue=newColor(0,OxFF,0);een=newColor(0,0,OxFF);ite=newColor(0,0,0);方法Methodsー个方法是ー个可以实现由对象或类所能完成的计算或操作的元素。方法可以有一些正式的元素(可以为空),一个返回值(或void),并且可以是静态或非静态的。静态方法可以通过类来访问。非静态方法,也叫作例程方法,可以通过类中的例程访问。例子usingSys(em;publicclassSlack(publicstaticStackClone(Stacks)(...)publicstaticStackFlip(Stacks){...)publicobjectPop()(...|publicvoidPush(objecto){...)publicoverridestringToString()(...|classTestIstaticvoidMain()(Stacks=newStack();for(inti=1;i<10;i++)s.Push(i);Stackflipped=Stack.Flip(s);nケ,vr,Tnケ,vr,T〇WWWceeeK000csssannnゝccciteLine("Originalstack:"+s.ToString());iteLine("Flippedstack:"+flipped.ToString());iteLine("Clonedstack:"+cloned.ToString());)I中有一个包括几个静态方法(Clone和Flip)和几个例程方法(Push、Pop和ToString)的堆栈。方法可以重载,这意味着多个方法可以有相同的名称,只要它们有不同的信息签名。ー个方法的信息由方法名称和它正式参数的数目、修饰符和类型构成。方法的信息并不包括返回类型。例子classTest(staticvoidF()(Console.的ileLine("F()");IstaticvoidF(objecto){Console.5WiteLine("F(object)");)staticvoidF(intvaIue){Console.WiteLine("F(int)");)staticvoidF(inta,intb)(Console.W-iteLine(WF(int,int)");IstaticvoidF(int(]vaIues)|Console.WiteLine(wF(int(])");staticvoidMain()|F();F(1);F((object)1);F(1,2);F(newint[]{1,2,3});I)中由一个类,包括多个方法F。程序的输出为:FOF(int)F(object)F(int,int)F(int[])属性通过属性可以访问ー个对象或类的性质。属性的例子包括字符串的长度、字体的大小、窗体的标题、用户名称等等。属性是域的自然延伸。两者都是命名的、和类型相关的元素,访问域和属性的方法也类似。然而,和域不同,属性没有指定存储地址。相反,属性有存储器,可以指定执行语句来读写它们的值。属性由属性声明语句定义。属性声明的第一部分和域声明的第一部分相似。第二部分包括ー个get操作符和ノ或ー个set操作符。在下面的例子中,Button类定义了一个Caption属性。publicclassButtonIprivatestringcaption;publicstringCaption(get(returncaption;)set(caption=va1ue;Repaint();)))属性可以读和写,例如Caption属性,包括get和set操作符。要读取属性的值时,调用get操作符,要写入属性的值,调用set操作符。在set操作符中,属性新的值以名为value的默认参数形式给出。属性的声明相对简单,但属性的真正值是在使用的时候而不是声明的时候显示的。Caption属性的读写和域的读写是ー样的:Buttonb=newBu11on();b.Caption="ABC";//setstrings=b.Caption;IIgetb.Caption+="DEF";//get&set事件Events事件是ー个对象或类可以定义的元素。ー个类通过事件声明来定义一个事件,和一个域或事件的声明类型,只是增加了一个addedevent关键字。声明的类型必须是ー个delegate类型。publicdelegatevoidEventHandler(objectsender,Evente);publicclassButton(.publiceventEventHandlerClick;publicvoidReset()(Click=null;中Button类定义了一个类型为EventHandler的Click事件。在Butlon类中,Click元素对应一个类型为EventHandler的私有域。然而,在Button类外,Click元素只能在操作符+二和・ニ的左边使用。这个限制了客户程序增加和删除事件句柄。例子usingSystem;publicclassFormlIpublicForml(){11AddBu11on1_C1ickasaneventhand1erforButtonl'sClickeventButton1.Click+=newEventHandler(Buttonl_Click);)ButtonButtonI=newButton();voidButtonl.Click(objectsender,Evente){Console.iteLine("ButtonIwasclicked!");)publicvoidDisconnect(){Button1.Click-=newEventHandler(Button1Click);)(中有一个Forml类,为But【on1的Click事件加入了Buiton1_CIick作为事件句柄。在Disconnect方法中,删除这个事件句柄。可以应用属性类似事件声明而不是域类似事件声明来重写ButIon类。如下面的例子所示:publicclassButton(publiceventEventHandlerClick{get(...IpublicvoidReset()(Click=nul1;))这个变化不会对客户程序产生影响,但使得Button类实现更加灵活,因为Click的事件句柄没有必要必须用ー个域来表示。操作符操作符定义了可以被类的例程使用的操作的含义。总共有三种类型的操作符:一元操作符、二元操作符和转换操作符。ド面的例子定义了一个Digit类型表示十进制数字-0和9之间的整数值。usingSystem;publicstructDigit(bytevaIue;
publIcDigit(bytevaIue){if(va1ue<011value>9)thrownewArgument1ue=va1ue;this).vapublicDigit(intvalue):this((byte)va1ue)()publicstaticimp1icitoperatorbyte(Digitd)(retuIrnd.va1ue;publicstaticexplicitoperatorDigit(byteb)|retu)rnnewDigit(b);publicstaticDigitoperator+(Digita,Digitb)newDigit(a.value+b.va1ue);retu)rnpub1icstaticDigitoperator*(Digita,Digitb)retu)rnnewDigit(a.value-b.va1ue);publicstaticbooloperator==(Digita,Digitb)retu)rna.va1ue==b.va1ue;publicstaticbooloperator!=(Digita,Digitb)retu)rna.va1ue!=b.va1ue;public0VerrideboolEqua1s(objectva1ue){retu)rnthis==(Digit)va1ue;pub1ic0VerrideintGetHashCode()(retu)rnva1ue.GetHashCode();public0VerridestringToString(){returnva1ue.ToString();)classTes(IstaticvoidMain()(Digit a= (Di gi t ) 5;TOC\o"1-5"\h\zDigit b= (Di gi t ) 3;Digit plus= a + b;b〇〇〇="!(!(--=eeenualwwwb〇〇〇="!(!(--=eeenualwww1boolequConsole.Console.Console.)1Digit类型定义了下面的操作符:«ー个从Digit到byte的默认转换操作符。»ー个从byte到Digit的默认转换操作符。«ー个相加操作符,将两个Digit值相加并返回一个Digit值。«一个相减操作符,从ー个Digit值中减去另外一个值,并返回ー个Digit值。«ー个等于(==)和不等于(!=)操作符,用于比较两个Digit的值。索引应用索引可以使得一个对象可以类似数组的方式索引。属性提供了类似于域的访问,而索引提供了类似于数组的访问。以前面所列的Stack类为例子。这个类需要提供类似于数组的访问方式,以便不需要执行Push和Pop属性即可得到或改变项目的值。Stack是通过类似于列表的方式实现的,但没冇数组访问的便捷性。索引声明和属性声明类似,主要的区别在于索引是没有名称的(在声明中的“名称”是this,因为this是索引的)并且索引包括索引参数。索引的参数用方括号括起来。例子usingSystem;publicclassStack[privateNodeGetNode(intindex)(Nodetemp=first;whiIe(index>0)(temp=temp.Next;returntemp;)publicobjectthis(intindex]{get(if(IValidlndex(index))thrownewException("Indexoutofrange.");elsereturnGetNode(index).VaIue;)set(if(IValidlndex(index))thrownewException("Indexoutofrange.");elseGetNode(index).Vaiue=vaIue;))classTestIstaticvoidMain(){Stacks=newStack();s.Push(1);s.Push(2);s.Push(3);TOC\o"1-5"\h\zs[0] = 33; // Changes the topitemfrom3to 33s[11 = 22; // Changes the middIeitemfrom2 to 22s[2j = 11; // Changes the bottomitemfromI to 11I)显示了Stack类的ー个索引。例程构造函数例程构造函数用于实现所需要的初始化ー个类例程的功能。例子usingSystem;classPointIpublicdoublex,y;publicPoint(){this.x=0;this.y=0;IpubIicPoint(doubIex,doubley)(this.x=x;publicstaticdoubleDis(anee(Pointa,Pointb)(doublexdiff=a.x-b.x;doubleydiff=a.y-b.y;returnMath.Sqrt(xdiff*xdiff+ydiff♦ydiff);)publicoverridestringToString()(returnstring.Format("((0),|I|)",x,y);I1classTestIstaticvoidMain()(Pointa=newPoint();Pointb=newPoint(3,4);doubled=Point.Distance(a,b);Console.W-iteLine("Distancefrom(0)to(I)is[2ド,a,b,d);I1中有・个Point类,其中提供了两个公共构造函数。ー个Point构造函数不包含参数,另外一个有两个参数。如果没冇给类提供构造函数,一个无参数的公共构造函数将自动加入到类中。析构函数析构函数用于完成所需要的解构一个类实例的功能。析构函数没有参数,没有访问修饰符,也不能确切调用。ー个实例的析构函数在资源回收
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年房屋终止合同协议书模板
- 六年级下册数学教案-数学好玩2《神奇的莫比乌斯带》 |北师大版
- 2024-2025学年六年级下学期数学第二单元圆柱和圆锥的综合复习(教案 )
- 五金厂的劳动合同(2025年版)
- 二年级上册数学教案-3.2 儿童乐园-北师大版
- (高清版)DB45∕T 838-2021 三江侗族自治县侗族百家宴服务规范
- 2025年湖南工艺美术职业学院单招职业技能测试题库一套
- 【单元测试】部编版语文三年级上册第六单元分层训练B卷(提升篇)-(含解析)
- 2024年海洋石油修井机项目投资申请报告代可行性研究报告
- 2024年年物流仓储项目资金需求报告代可行性研究报告
- 2024年医院感染管理制度(四篇)
- 部编版语文三年级下册综合性阅读-理解人物情感-课件-(共32张课件).课件
- 2024年中国甜瓜市场调查研究报告
- (中级)航空油料特设维修员(四级)理论考试题库-上(单选题)
- 部编人教版六年级道德与法治下册全册完整版课件
- 电动车辆动力电池系统及应用技术 第3版 课件全套 王震坡 第1-11章 动力电池及其驱动的电动车辆- 动力电池充电方法与基础设施
- 【独立储能】山西省独立储能政策及收益分析-中国能建
- (正式版)CB∕T 4550-2024 船舶行业企业安全设备设施管理规定
- 新入职员工廉政谈话
- JB∕T 9006-2013 起重机 卷筒标准规范
- 2024内蒙古中考数学二轮专题复习 二次函数与几何综合题 类型二 面积问题(课件)
评论
0/150
提交评论