C#基础语法及面向对象概念_第1页
C#基础语法及面向对象概念_第2页
C#基础语法及面向对象概念_第3页
C#基础语法及面向对象概念_第4页
C#基础语法及面向对象概念_第5页
已阅读5页,还剩24页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

程序控制语句是否每次循环都会在该循环体作用域内垃圾回收一次。if语句控制if的条件表达式必须生成bool型结果。if-else-if阶梯式结构if(条件)语句;elseif(条件)语句;elseif(条件)语句;else语句;switch格式:switch(表达式){case结果1;语句;break;case结果2;语句;break;default;语句;break;}switch表达式必须是整数(包括char型)或string类型,浮点表达式是不允许的。case常数必须具有与表达式相兼容的类型的常量,在同一switch中任何两个case常数的值都不能相同。如果没有case常数与表达式匹配,则执行default语句,是否有default是可选项的。case的序列必须要用break结束,否则会接入下一个case出错,这称为不可入规则。但是你可以将多个case常数指向同一段代码,如:switch(i){case 1;case 2;case 3;Console.WriteLine("iis1,2or3");break;case4;Console.WriteLine("iis4s");break;}for循环for(初始化循环变量;条件;重复变化量)例如:for(i=i;i<10;++i){Response.write(i);}“条件”的结果必须为bool值,但可以不包含循环变量。循环变量的作用域仅限for循环体多个循环变量可以在表达式中使用多个变量来控制循环,变量之间用逗号间隔:for(i=0,j=10;i<j;i++,j--) Response.Write("iandj:"+i+"+"+j);缺省空白在for中初始部分、条件、重复变化部分,都可以为空如:for(i=0;i<10;)在循环体内部进行i运算for(;i<10;) 必须事先初始化i,在循环体内部进行i运算for(;;)无限循环没有循环体的循环例如:对1至50累加:intsum=0;for(i=1;i<=50;sum+=i++);在循环体只有一条语句时,完全可以采用这种方法。for(;DataReader1.read();Response.Write(DataReader1["name"]));while循环while(条件){循环体}条件为真时执行do-while循环do{循环体}while(条件)do-while循环是在未尾判断条件,这意味着循环至少会被执行一次,在某些情况下可以减少代码量。break利用break可以强制跳出循环,并略过本次循环的剩余代码。Continue略过本次循环的剩余代码,提前进入下一次循环。goto跳转无条件跳转到指定位置,如:loop1: //标签,标签后跟冒号x++;if(x<10)gotoloop1; //无条件跳到loop1处goto鼓励创造无头绪代码,然而有时却能使程序更加清晰和便捷,比如从深层嵌套中退出。foreach循环foreach(类型形参变量in数组或集合){}形参变量必须与数组集合的基本类型相同或兼容foreach也可用于多维数组,遍历其中的第一维,按照行的顺序从头到尾返回减少了一维的子数组。继承继承首先建立一个通用类,定义出公用的特性。可以被其他更具体的新类继承,在每个新类中都添加特有的性质。那么,被继承的类叫做基类,继承后产生的类叫做派生类。因此,派生类是基类的特殊版本。它继承了基类的所有变量、方法、属性和基类定义的索引。继承声明C#类声明中允许集成另一个类,这要通过声明派生类时指定基类来完成。如:class派生类名:基类名{}尽管派生类继承自基类,但它完全是一个独立的类。而基类也完全可以按照独立类来使用。你只能为任何一个新建的派生类指定一个基类,C#不允许多个基类共同派生出一个新。然而派生类可以作为另一个派生类的基类。派生类无法继承基类的private私有成员。但我们有其它方法来访问基类的私有成员:protected访问修饰符和用属性来访问私有数据。protected访问修饰符protected保护成员在类的层次结构外被认为是私有成员。类成员被声明为protected后实际上是私有的,但它会被继承到派生类,因此可以被派生类访问。构造函数的继承性基类的构造函数构造对象的基类部分,派生类的构造函数构造对象的派生类部分(后来添加的方法和变量)。构造函数的构造过程是分开的。在类的层次中,构造函数按照派生的顺序,从基类到派生类调用。而且无论是否使用base都会采用这种顺序。隐藏个人认为叫遮盖更贴切一点。派生类有可能定义和基类中名字相同的成员,此时,基类中的同名成员就会被隐藏。这并不算异常,但编译器会给出警告,提示你该成员被隐藏了。如果要隐藏基类成员并取消编译器警告,声明成员时要在前面加上new关键字(这与创建对象实例截然不同)。格式:new类型成员名;关键字base关键字base有两个用途:1.调用基类的构造函数2.访问派生类覆盖的基类成员调用基类的构造函数构造函数名(参数列表):base(参数列表){}base指的是调用类的上一级基类,如果没有base语句就自动调用基类缺省的构造函数如:classa{intt,n; publica(intx,inty){ t=x;n=y;}}classb:a{ints; publicb(inti):base(i,9){ //可以直接使用形参i,像在函数内部一样。 s=i;}}访问(被隐藏的)基类成员用法类似于this,只不过它引用的是基类。用法:base.成员名方法、实例变量、属性均可。base.show(); //引用基类的show()方法引用与继承一个类型的引用变量通常不能引用另一个类类型的对象。(除了类型兼容外)可是,C#允许基类的引用变量赋给该基类的任何一个派生类的对象。但此时只能访问基类中已定义的基类成员,因为基类不知道派生类添加的信息。虚方法和重载个人认为所谓虚方法,就是可以被派生类覆盖的方法。(这与用new隐藏一个基类方法有什么不同?)基类中将一个方法声明前加上关键字virtual,该方法就被认为是虚方法。当派生类重新定义虚方法时,就要使用override修饰符。这种派生类重新定义虚方法的过程被称为方法重载。虚方法不能被定义为static或abstract。方法重载形了C#的一个重要概念:动态方法分配。动态方法分配是一种在程序运行时,而不是在编译时调用重载函数的机制。运行期多态就是靠它实现的抽象类与抽象方法抽象类:相当于只定义一个被所有派生类共享的基本形式,派生类实现类的功能细节。抽象类不能实例化对象,否则会导致编译错误。abstractclass类名{}抽象方法:相当于一个没有被代码实现的虚方法(但virtual和abstract一起使用是错误的)abstract返回类型方法名(参数列表);不能将静态方法设置的抽象方法包括抽象方法的类必须也声明的抽象类当一个派生类继承了一个抽象类时,该类就必须实现基类的所有抽象方法,除非这个派生类也是abstract抽象类,则其中的抽象方法就可以不用实现而继续的继承下去。封装使用封装可以防止一个类被继承。关键字sealed用于实现封装。在类声明前加上sealed即可,但一个类声明中不能既有abstract又有sealed。sealedclassA{}object类所有的类皆派生于object类(System.Object)。也就是说object是任何类型的“兼容类型”。这意味着,类型为object的引用变量可以引用其他任何类型的对象。object中的方法方法目的publicvirtualboolEquals(object对象名)决定当前对象是否和object的引用相同publicstaticboolEquals(object对象1,object对象2)决定对象1是否和对象2指向同一个对象publicvirtualintGetHashCode()返回当前对象相关的散列码publicTypeGetType()运行时获取对象的类型publicstaticboolReferenceEquals(object对象1,object对象2)决定对象1是否和对象2指向同一个对象publicvirtualstringToString()返回描述对象的字符串装箱:当一个“object类引用”引用了值类型时,就发生了装箱操作。装箱使得值类型的数值被存到对象实例中。被“装”在object类型中,像对象一样被使用。装箱操作是自动进行的,你只需赋值给object类型的引用。拆箱:是从对象获取值类型的过程。这个操作执行了从object类型引用到期望的值类型的转换。x=10;obj=x; //x被装箱到对象中inty=(int)obj; //对象obj被拆箱到整型变量中接口

接口相当于只定义了类的结构,但没有定义类的实现细节。接口中没有一个方法和实体,无论如何接口都不会提供实现细节。一个接口可以被许多类继承并实现,一个类也可以继承并实现许多接口。接口方法声明格式:interface接口名{返回类型方法名{参数列表};返回类型方法名{参数列表};返回类型方法名{参数列表};}包含接口的类必须实现所有的方法。接口中的方法默认为public,不用显式指明。继承接口:class类名:接口名{}接口引用你可以创建接口引用变量。只能先建立实现接口的类的实例,然后将类实例转换为接口类型,不能用new构造接口实例。一般情况下,采用将类实例转换为接口引用来访问接口是一种更好的接口访问方式,不过很多情况下,我们不知道对象是否支持某个接口,这时,可以试图将对象转换为接口处理,并利用try/catch进行判断处理。接口属性声明格式:interface接口名{类型属性名{ get; set;}}接口索引:声明格式interface接口名{返回类型this[int变更名]{ get; set;}}接口继承接口一个接口可以继承另一个接口,语法和继承类的一样:

publicinterfaceB:A{}显式实现接口也就是写清全名,如在继承了接口的类中使用“接口名.成员名”的方式interfaceA{ intNa();}classB:A{ intA.Na(){ //接口的显式实现 Response.write("已执行");}}原因有二:一个类有可能同时实现了两个接口,如此可处理同名成员。当使用全称作用域实现一个方法时,就相当于提供了不是处于类外代码的一个私有实现。(意思是否指这个方法实质上不属于定义它的类)结构类是引用类型,值类型可以被直接访问。结构颇似于类,但它是值类型。使用关键字struct声明结构:struct结构名称:接口名称{ //成员声明}结构不能继承其他结构或类,也不能被类继承。可是,结构能够用来实现一个或多个接口(用逗号分隔)。structaccount{ publicstringname; publicdoublebalance; publicaccount(stringn,doubleb){ name=n; balance=b;}}类(对象与方法)类是一种抽象的逻辑,一个设计合理的类应该只包含一个逻辑实体。类组织那些逻辑上有联系的信息。把逻辑上无关的信息放在同一个类中会破坏代码的一致性。在技术上,在有创建了类的对象实例,类才物理的体现在内存中。构建类的变量和方法都称作该类的成员。类为引用类型。类的形式当你在程序中定义一个类时,你声明了该类应当包含的数据和操作这些数据的代码。定义类:class类名{//访问修饰符类型成员名;publicintmpg;}定义一个类实际上就是创建了一个新的数据类型当在一个类中使用类成员时,可以直接使用,而不必使用点运算符,因为类也是一个作用域。Main程序入口方法Main()和Page_Load()方法一样,是一个类中会自动运行的方法,但一般形式的类并不指定Main()方法,只有当你的类是程序的入口点时才有必要这样做。Main()方法是一个应用程序的入口,当它所在的类是程序的入口点时,该方法会在应用程序启动时自动执行。从Main()返回值当程序结束时,可以通过Main()向调用它的程序(通常是操作系统)返回一个值。publicstaticintMain();按惯例,返回值为0通常表示程序正常终止。返回其他值都表示出现了某种类型的错误。向Main()传递参数许多程序都接收命令行参数。命令行参数是在命令行中直接跟在程序名后面的信息(如:format-q-s)。对于C#程序,这些参数都会传递给Main()方法。为了接收这些参数,必须使用如下的Main()形式:publicstaticintMain(string[]args);//接收到的是一个字符串数组对象的创建格式:访问修饰符类对象名=new构造函数();publicCarmyCar=newCar();此处,该声明创建了对象的实际物理拷贝,并把它赋值给myCar变量以引用对象(myCar只是一个引用变量)。new运算符为对象动态分配内存,并返回该对象的一个引用,这个引用是用new分配到的对象的内存地址。方法格式:访问修饰符返回值类型方法名(参数列表)publicintaddNum(inta,doubleb){ returna+b;//方法体;}其中,返回值类型是指该方法返回数据的类型,它可以是任何有效类型(类也是数据类型)。参数列表是用逗号隔开的类型、标识符对。形参本质上是变量,它用来在调用方法时接收实参传来的值(形参只在方法内部有效)。如没有参数接收为空即可。如果参数为值类型,则形参为其值的copy,如果参数为对象类型,则形参为其对象引用。returnreturn用于从方法返回一个值给调用者。返回数据类型必须与该方法定义时指定的返回数据类型相一致。用于从方法返回一个值并跳过剩余代码,或在void方法中起到提前结束方法的作用。(可以使用多个return以应对多个分支)returnnewErr(errInfo); //构造并返回对象一般而言,带有返回值的方法可以参与表达式的运算。ref参数使方法传递参数时,可以作为引用来接收实参,这样方法就有能力改变实参本身的值了。注:实参在调用前必须赋值,不能用方法给使用ref的实参赋初值。sqr(refinti){ i=i*i;}...inta=10;sqr(refa);a值变为100out参数out与ref参数功能相同,唯一区别是:实参在调用前不必赋值,可以用方法给使用out的实参赋初值。sqr(outinti){ i=10; i=i*i;}...inta;sqr(outa);a值变为100ref与out参数支持原本就是引用类型的实参,得到的是引用变量本身,而不新建一个变量。这样我们就可以在方法中改变“实参引用变量”所指的对象了。可变数量的参数方法的形参中params修饰符用来声明一个数组参数,这个数组参数可以接收0个或多个实参。该数组长度与所传递实参个数相同。(说白了就是接收一个数组)voidshowArgs(stringmsg,paramsint[]nums){ ...}showArgs("test",1,2,3,4,5);当方法既有正规参数又有params参数时,params参数必须位于参数表的最后面。而且,在任何情况下都只能有一个params参数。方法重载在C#中,只要它们的参数声明的不同,同一个类中的两个或更多方法可以拥有相同的名字,这种情况就称为方法的重载,重载可以使一个方法适应多种不同的传参情况。每个重载的方法,参数类型和个数必须不同。但是可以有不同的返回值类型。构造函数构造函数在对象创建时初始化对象。它和类的名字相同,语法上类似方法,区别是没有返回值。定义格式访问修饰符类名(){ //构造函数代码}你可以使用构造函数给类中所定义的实例变量赋一个初值,或者执行一些在创建对象时就必需执行的初始化操作。在没有定义构造函数的情况下,C#自动定义一个缺省的构造函数来把类中定义的实例变量初始化为0(对于值类型)或null(对于引用类型)。但是,一旦你定义了自己的构造函数,缺省的构造函数就不再使用。当一个对象被创建时,该构造函数被new调用,如:MyClassti=newMyClass();注:构造函数通常被指定为public,这是因为它要被外部代码调用,用以构造一个类。(当没有足够内存时new可能不能为一个对象实例分配内存。否则将发生异常,我们实际编程时还是有必要注意这种可能性的。)构造函数中可以使用return来跳过剩余代码值类型也可以使用构造函数:inti=newint();带参数的构造函数:如果你的构造函数需要接收参数,可以用与方法接收参数格式相同的语法:ClassMyClass{ publicintx,y; publicMyClass(inti,intn){ x=i;y=n;}}MyClasst1=newMyClass(10,9); //调用构造函数构造函数的重载在C#中,只要它们的参数声明的不同,同一个类中可以有多个构造函数,这种情况就称为构造函数的重载,重载可以使构造函数适应多种不同的传参情况。通过this用一个构造函数调用另一个构造函数(参数列表):this(匹配的形参);ClassXYCoord{ publicintx,y;publicXYCoord(inti,intj){ Console.WriteLine("InsideXYCoord"); x=i; y=j;}publicXYCoord():this(0,0){ Console.WriteLine("InsideXYCoord");}publicXYCoord(XYCoordobj):this(obj.x,obj.y){ Console.WriteLine("InsideXYCoord");}}其中this(0,0)相当于调用XYCoord(0,0),系统自动匹配到XYCoord(inti,intj)。而XYCoord的实例obj.x和obj.y也是int型,所以依然自动匹配到XYCoord(inti,intj)。通过this调用重载构造函数很有用,原因之一是它避免了不必要的代码重复,第二是方便方法更好的适应带有“隐含实参”的构造函数,以使构造函数可以在实参没有明确指明的情况下使用。垃圾回收new运算符可在内存池中动态的为对象分配内存,而C#的垃圾回收系统则自动回收对象占用的内存。其工作原理:当一个对象没有对其的引用存在时,该对象就被认为不再需要了。垃圾回收是偶尔发生的,且其工作耗时,系统只会在有必要的情况下经行回收,因此你不可能精确知道垃圾回收是什么时候发生的。析构函数个人认为析构函数相当于一个事件,在对象即将被垃圾回收前调用,在其中你可以指定那些必须在对象销毁前完成的行为。格式:~Class-name(){ //是否支持参数传入? //操作}记住,有可能程序在垃圾回收以前就结束了,在这种情况下析构函数根本不会被调用。this关键字当调用一个方法时,自动传递一个隐含的参数,该参数引用调用对象,其引用参数为this。类成员的访问实际上成员只有两大基本访问类型:共有和私有访问修饰符:public、private、protected、internal。如果不定义任何修饰符,一个类成员会被默认为private同一个类的成员可以访问类中的私有成员Main()方法Main()方法是一个应用程序的入口,当它所在的类是程序的入口点时,该方法会在应用程序启动时自动执行。从Main()返回值当程序结束时,可以通过Main()向调用它的程序(通常是操作系统)返回一个值。publicstaticintMain();按惯例,返回值为0通常表示程序正常终止。返回其他值都表示出现了某种类型的错误。向Main()传递参数许多程序都接收命令行参数。命令行参数是在命令行中直接跟在程序名后面的信息(如:format-q-s)。对于C#程序,这些参数都会传递给Main()方法。为了接收这些参数,必须使用如下的Main()形式:publicstaticintMain(string[]args); //接收到的是一个字符串数组递归递归是一个用本身去定义它自己的过程。递归方法的关键是它包含一个调用自身的语句。理解静态static当成员声明为static时,不需要通过对象对其进行访问,对它的访问可以发生在类的任何对象创建之前。方法和变量都可以声明为static。最普通的static成员的例子是Main()方法。在类外使用static成员必须指明类的名字。static成员不能通过对象实例来访问,它必须通过类名进行访问。除了使用类名外,其格式与通过对象访问普通类成员相似。static静态变量被声明为static的变量是全局变量,static变量在类被装载时初始化。如果没有明确的初始化设置,数值类型将被初始化为0,引用变量(包括string)初始化为空,bool变量初始化为false。因此,static变量总有一个值。static静态方法有几点限制1.static方法不能引用this。2.static方法只能直接调用其他static方法。它不能调用类中的实例方法。原因是实例方法作用于类中的特定实例,但static方法不是。3.static方法只能直接访问static数据。它不能使用实例变量,原因是它不作用于类的实例。如果static方法需要调用对象实例的方法和变量,就必须通过一个对象实例来进行。静态类:不能被new实例化的类staticclassConsoleHelper{publicstaticintReadInt(){}}1、静态类内部成员必须是静态的。2、静态一般在程序加载的时候被构造。3、如果要在静态类中使用非静态类,那么你需要在任何有可能访问到他的代码前手动初始化他,并且还要将他赋给一个静态变量后才能使用。4、静态类可以有构造函数,但是只被调用一次。非静态类使用完成后系统会自动销毁释放,所以非静态类相对来说比较安全,而静态类是在程序结束后销毁的,在销毁前一直驻留在内存中,因此出现错误的可能性会大些。建议不要过多的使用静态类,适时使用。运算符重载C#允许定义运算符相对于自定义的类的意义。这个过程叫做运算符重载。重载后的运算符在类中的使用得到了扩展。运算符的作用完全在你的控制之下,并且在各个类之间可以不同。例如,一个定义链表的类可能用+表示在链表中加入一个对象,一个堆栈类可能用+来表示压栈操作。 当运算符被重载时,它本来的意义不会丢失,而只是增加了一个对于特定类的新操作,并不意味着改变了"+"对于整数的意义。不能为非自定义类重载任何运算符,如:int、string。重载一元运算符的一般形式:publicstatic返回类型operator运算符(参数类型操作数){//操作并返回值}对一元运算符来说,操作数类型必须与运算符所在类相同。如:publicstaticThreeDoperator++(ThreeDa){}重载二元运算符的一般形式:publicstatic返回类型operator运算符(参数类型操作数1,参数类型操作数2){//操作并返回值}例如将两个三维坐标对象相加:classThreeD{intx,y,z;publicstaticThreeDoperator+(ThreeDa,ThreeDb){ ThreeDr=newThreeD(); r.x=a.x+b.x; r.y=a.y+b.y; r.z=a.z+b.z; returnr;}}逻辑运算符也可以被重载,但是为了运算有意义最好还是返回bool值。但这里有一条重要限制:逻辑运算符的重载必须成对:== !=< ><= >=必须两两相对,不能只重载其中一个。(如果重载==和!=则通常需要重载Object.Equals()和Object.GetHashCode()方法)运算符重载的限制赋值运算符(复合赋值运算符,如+=)和以下运算符不能被重载:&& || [] () new is sizeof typeof ? -> . =注:如果定义了+运算符,在进行+=运算时则会自动调用+运算符。索引器索引允许对象(一个类的多个对像实例)像数组一样被检索。索引可以是一维,也可以是多维的。(主要用途是支持创建受诸多制约的选定数组)实际需要时再补充本章内容结构体C#中结构类型和类类型在语法上非常相似,他们都是一种数据结构,都可以包括数据成员和方法成员。因为结构是值类型,性能会非常好,因为他们将内联或者保存在堆栈中。当把一个结构类型的变量赋值给另一个结构时,对性能的影响取决于结构的大小,如果结构的数据成员非常多而且复杂,就会造成损失,接下来使用一段代码来说明这个问题。结构和类的区别:1、结构是值类型,它在栈中分配空间;而类是引用类型,它在堆中分配空间,栈中保存的只是引用。一、声明结构的语法-struct关键字publicstructAddressBook{//字段、属性、方法、事件}结构

数据类型值类型引用类型

是否必须使用new运算符实例化否是

是否可声明无参数的构造函数否是

数据成员可否在声明的同时初始化声明为const或static可以,数据成员不可以可以

直接派生自什么类型System.ValueType

是否有析构函数无有

可否从类派生否可以

可否实现接口可以可以

实例化时在栈还是在堆分配内存栈堆,栈中保存引用

该类型的变量可否被赋值为null否可以

可否定义私有的无参构造函数否可以

是否总有一个默认的无参构造函数

是否

==================================属性个人认为属性更像是字段(类中的变量)的一个接口,其本身并没有存储值的功能,一个属性包含一个名字、get和set访问函数:类型属性名{ get{ //取值操作}set{ //赋值操作}}//也可以定义只读和只写的属性,要定义只读属性,就只定义get访问函数,要定义只写属性,就只定义set访问函数。异常C#中异常是以类的形式出现的,所有异常类都必须继承自内建的位于System名字空间中的Exception异常类。把想要监视的语句放在一下try块中,使用catch块可以捕获到异常,并处理异常。格式:try{ //受监视的代码块}catch(异常类型1接收异常的对象1){ //处理异常1}catch(异常类型2接收异常的对象2){ //处理异常2}如果异常类型匹配catch语句的指定,那么只有这个catch语句都才会被执行,其他catch语句都会被忽略。catch语句可以不指定“接收异常的对象”,如此它将捕获所有异常。catch{}再次抛出的异常,是不会被同一个catch语句捕获到的,它会传播到下一个catch语句try块可以嵌套throw使用关键字throw可以人为抛出异常:thrownewDivide();注意:在throw语句中如何使用new来创建Divide异常,因为throw抛出的是对象,因此必须创建一个用于抛出的对象。也就是说,不可以仅仅抛出一个类型。数据类型与运算符整数类型C#定义了九种整数类型:char、byte、sbyte、short、ushort、int、uint、long、ulong(其中char类型主要是用来描述字符的,其它8种是用来进行数值计算的)类型位宽范围byte80~255sbyte8-128~127short16-32768~32767ushort160~65535int32-2147483648~2147483647uint320~4294967295long64-9223372036854775808~9223372036854775807ulong640~18446744073709551615char160~65535浮点类型float单精度(32位宽),取值作用域1.5E-45到3.4E+38double双精度(64位宽),取值作用域5E-324到1.7E+308.net框架库中许多数学函数使用double数值,因此double类型的应用比较普遍字符char代表Unicode定义的一个字符集。虽然它是整数类型,但是不存在char类型向整数类型的隐式转换。布尔类型Bool和整数之间没有定义转换关系。例如:1不能转换为true,0也不能转换为false。字符转义序列字符转义序列:代表在字符串中含有特殊意义的字符,它们会被转义为其它作用,而不是按原格式显示。转义字符序列描述\a警报(铃)\b退后一格\f换页\n新的一行(换行)\r回车\ttab水平制表符\v垂直制表符\o空\’单引号\”双引号\\反斜杠原(逐)字符串原字符串以@开始,引号内的内容在被接受时是不变的(即使其中有转义符),并且可以跨越多行。所以,我们可以在其中包含新行、制表符等,而不必使用字符转义序列。唯一例外是如果要包含双引号必须使用两个双引号。例如:Console.WriteLine(@”Thisisashowstring1 2 3 4““IlikeC#”””);输出显示如下:Thisisashowstring1 2 3 4“IlikeC#”然而对于多行字符串,这种方式会导致程序显示不清晰。变量声明当使用一个用逗号作分隔符的列表来声明两个或更多的同一类型的变量时,你可以给其中的一个或多个变量赋初始值。inta,b=8,c=19,d; //b和c已经被初始化注:变量的类型在整个生存周期内不能改变变量的作用域和生存周期正常情况下一对{}就代表一个块,一个块包含在一对花括号中,每个块代表一个作用域。(包括if{},for{}等)声明变量时其所在的位置块就是该变量的作用域,作用域也决定了这些变量对象的生存周期。对象在离开其作用域时会被清除。并且,作用域内声明的变量对于作用域外部定义的代码是不可见的方法定义的作用域是从左花括号开始的,但是,如果一个方法有参数,那参数也包括在方法的作用域内。作用域内声明的变量(默认情况下)对于其外部定义的代码是不可访问的。因此作用域内声明的变量已被局部化,以防止受到未经授权的访问或修改。(在子作用域中声明的变量不能与父作用域已有变量重名)但是,外层作用域声明的对象对内层是可见的(即子块可访问父块对象)。运算符:C#包含四大类通用运算符:算术运算符、位运算符、关系运算符和逻辑运算符。算术运算符+ 加- 减* 乘/ 除 (对整数进行除运算时,余数都被舍去了。例如:10/3=3)% 模数运算 (整数和浮点类型都可以进行模数运算)++ 增量运算 ++X前缀格式,X++后缀格式。(当++运算是一条单一语句时,两种格式没有任何区别,但是当其被运用在一个较大的表达式中时,前缀格式表示在取得操作数的值之前执行++运算,而后缀格式表示先取得操作数的值,然后再进行++运算)-- 减量运算 同上关系运算符和逻辑运算符关系运算符运算符含义==等于!=不等于>大于<小于>=大于或等于<=小于或等于逻辑运算符运算符含义&与|或^异或||逻辑或("短路"或)&&逻辑与("短路"与)!非注:在一个“与运算”中,如果第一个操作数是假,,不管第二个操作数是什么值,结果都为假。在一个“或运算”操作中,如果第一个操作数是真,不管第二个操作数是什么值,结果都为真。标准和“短路”版本的唯一区别就是,标准版本会对每个操作数求值,而“短路”版本只在必要时才对第二个操作数求值。赋值运算符=赋值链C#允许你创建一个赋值链,如:intx,y,z;x=y=z=100;复合赋值算术运算符+= -= *= /= %=逻辑运算符&= |= ^=使用复合赋值在编译时能产生效率更高的代码(因为操作数只被计算一次)。赋值中的类型转换符合下面将自动发生类型转换(隐形类型转换):1.两个类型是兼容的(请查阅类型兼容性)2.目的类型比源类型的作用域大。从long到double可以进行自动的的转换,但是从double到long就不可以了,因为从double到long是不兼容的。在decimal和float或double之间,从数字类型到char或bool都不能进行隐式的类型的类型转换。char和bool之间也不兼容。强制类型转换如:b=(byte)i;注意:长度长的类型向长度短的类型进行转换时,可能会丢失信息。例如,当long转换为int时,如果long的值比int的作用域大,将会丢失信息,这是因为long值的高位被删除了。当浮点值转换为整数类型时,小部分将被截断并丢弃。如:1.23赋给一个整形变量时,结果就是1。表达式中的类型转换:在一个表达式中,在两个或更多的不同类型的数据互相兼容的时候,把它们混合在一起是可能的,在操作中它们会被转换为同一类型。例如,可以在一个表达中混合short和long,因为它们都是数字类型。下是转换法则:IF 一个操作数是decimal,那么其他的操作数被提升为decimal(除非是float或double)类型,这种情况会出错);ELSEIF 一个操作数是double,第二个操作数被提升为double;ELSEIF 一个操作数是float,第二个操作数被提升为float;ELSEIF 一个操作数是ulong,第二个操作数被提升为ulong(除非它是sbyte、short、int或long类型,这种情况会出错);ELSEIF 一个操作数是long,第二个操作数被提升为long;ELSEIF 一个操作数是unit,第二个操作数如果是sbyte、short或int类型,那么都提升为long;ELSEIF 一个操作数是uint,第二个操作数被提升为uint;ELSE 两个操作数都提升为int这个提升规则有两点要注意:首先,在一个表达式中不是所有的类型都能混合在一起。确切一点说:从float或double到decimal是不能进行隐式类型转换的,把ulong和任何有符号整数类型混合在一起也是不可能的。这些类型混合在一起时需要使用强制转换。表达式求值时,类型提升的只是被操作的值,变量本身的类型不会发生改变。数组数组是一组类型相同的变量的集合。一维数组声明格式:类型[]数组名=new类构造函数[元素个数]int[]sample=newint[10];(加强边界:定义了元素个数的数组,超越其上下界都会导致运行期错误。)0作为第一个元素的索引初始化数组:类型[]数组名=new类构造函数[值1,值2,值3]int[]sample=newint[10,9,8];或:int[]sample;sample=newint[10,9,8];数组的长度Length属性是指数组的“容量”,而不是当前实际元素个数,它是可以动态改变的。二维数组比如声明一个10行20列的二维整形数组int[,]table=newint[10,20]多维数组类型[,,,,]数组名=new类构造函数[元素个数,元素个数,元素个数,元素个数,元素个数]初始化多维数组类型[,,]数组名={ {值1,值2,值3}, {值1,值2,值3}, {值1,值2,值3}};注意:要用逗号分隔初始化块,并在闭括号后有一个分号。不规则多维数组就是声明时只定义了一维或其中几维的长度,而在未定长度的维数中再定义每个点对应的“纵坐标轴”的长度,而不是标准的正方型或立方体。比如:int[][]j=newint[3][];j[0]=newint[2];j[1]=newint[3];j[2]=newint[4];我们可以通过j[0].Length来任何单个数组的长度。字符串在许多其他的编译语言中,字符串是字符数组,但在C#中却不是这样。C#中,字符串是对象。而string本质上是一种引用类型。构建字符串char[]str={'t','e','s','t'};stringsstr=newstring(str);Console.WriteLine(sstr[0]);结果显示为t。像数组一样,字符串索引也是从零开始的。但索引只能用来获取字符,而不能用来给其赋新值。可以用+运算符来连接两个字符串。string是不可变的string对象的内容是不可变的。这就是说组成字符串的字符序列一旦建立,就不能改变。当字符串作出某些变化时,系统会创建一个新的字符串,不用担心丢弃的字符串发生了什么,因为c#自动回收不再使用的字符串对象。string引用变量可以自动改变他们指向的对象。只是指定的string对象的内容创建后不能被改变。StringBuilder类属于System.Text名字空间StringBuilder类创建内容可变的字符串对象(我想在内存足够的情况下应该是string执行效率更高,因为他不需要重新擦写内存)运算符"?"逻辑表达式?表达式1:表达式2;当逻辑表达式值为真时,计算并返回第一个表达式值,否则返回第二个表达式值。枚举枚举类型是一组命名整型常量的列表,它指出了该变量的所有可能的合法取值。声明格式:enumname{逗号分隔的标识符列表}例:enumcoin{pp,nn,dd,qq} //从0开始累加赋值for(i=coin.pp;i<=coin.qq;i++){ //coin枚举变量可以控制for循环 Response.Write(i);}运行结果:0123枚举是整形的,那么可以使用整型的地方就可以使用枚举值。枚举赋值:enumcoin{pp,nn,aa,dd=100,qq}值依次为:0,1,2,100,101委托与事件委托通俗的讲,委托是一个可以调用方法的对象。尽管方法不是对象,但它在内存中也是有物理地址的,此地址就是方法的入口点,也就是方法被调用的地址。方法的地址可以赋给委托。一旦一个代理引用了一个方法,就可以通过此代理来调用所引用的方法,而且委托引用的方法可以改变,这样同一个委任就可以调用多个不同的方法。委任的主要优势就是允许指定调用方法,方法不是在编译时确定的,而是在运行时才决定的。声明格式:访问修饰符delegate返回类型委托名称([参数列表])实例化委托:委托类型实例名称=new委托类型(表达式)其中,返回类型是委托所调用方法的返回值类型,参数列表是委托所调用方法的参数列表。一旦声明了委托,此委托就只能调用委托指定的与返回值类型和参数表相吻合的方法。委托不但可以调用对象实例的方法,还可以调用类的静态方法。示例:delegatestringstrMod(stringstr); //声明委托ClassDelegateTest{ //静态方法 StaticstringreplaceSpaces(stringa){Returna.Replace('','-')} //实例化委托(类似对象实例) strModstrOp=newstrMod(replaceSpaces);//通过委托访问方法str=strOp("Thisisatest.");}当实例化代理时,只指定你想要引用的代理的方法名。同时,所引用方法的特征必须与代理的声明相匹配。通过对象实例来实例化委托strModstrOp=newstrMod(so.replaceSpaces); 通过引用对象so来引用方法replaceSpaces多重委托委托最吸引人的一个特性是它支持多重委托。简单来说多重委托具有创建方法链表的能力,当调用代理时,所有的方法都会被自动调用。而且这样的链表非常容易创建,只要简单地实例化一个代理,并使用+=运算符就可以把方法添加到链表中。要想从链表中删除一个方法,只要使用-=就可以(也可独立使用+、-和=来进行增加、删除委托操作,但使用+=和-=更方便)。使用多重委托唯一的限制是:代理的返回类型必须声明为voiddelegatevoidD(intx);classCls{ publicstaticvoidM1(inti){/**/} publicstaticvoidM2(inti){/**/}}classTest{ staticvoidMain(){ Dcd1=newD(Cls.M1); //实例化委托M1 Dcd2=newD(Cls.M2); //实例化委托M2 Dcd3=cd1+cd2; //实例化委托(M1+M2) Dcd4=cd3+cd1; //实例化委托(M1+M2+M1) Dcd5=cd4+cd3; //实例化委托M1 cd5+=cd2; //(M1+m2)}}调用委托与调用类的方法格式相似。delegatevoidD(intx);publicclassMyCls{ staticDcd1=newD(Cls.M1;) Dcd2=newD(Cls.M2); ...}staticvoidMain(){ MyCls.cd1(3); //类名限定 MyClsCls=newMyCls(); //对象名限定 Cls1.cd2(5); ...}事件事件是C#中建立在委托基地上的另一个重要特性。事件发生时,会调用所有已注册的事件处理程序。事件处理程序用委托来表示。事件是类成员,并以关键字event声明:访问修饰符event委托类型事件名其中,“委托类型”代表支持事件的委托名称,“事件名”是所创建事件的名称。例:usingSystem;//为事件声明一个委托delegatevoidMyEventHandler();//声明事件类classMyEvent{ publiceventMyEventHandleractivate; //调用这个方法来触发事件 publicvoidfire(){ if(activate!=null) //只有当activate非空时,才能调用事件处理函数 activate();}}classEventDemo{ staticvoidhandler(){ Console.WriteLine("Eventoccurred");}publicstaticvoidMain(){MyEventevt=newMyEvent();//把handler()添加到事件链表中evt.activate+=newMyEventHandler(handler);//触发事件evt.fire();}}平时应用中也应该注意,调用事件之前,必须测试事件委托以保证它不为空。因为事件的触发是很难预测的,很可能发生在事件注册之前。所有的事件都是通过委托来激活的。多播事件事件可以像“多重委托”一样,支持一个事件调用多个方法。并可用加减运算符添加与删除:(部分代码同上例)evt.activate+=newMyEventHandler(handler);evt.activate+=newMyEventHandler(handler2);evt.activate+=newMyEventHandler(handler3);预处理指令预处理指令C#定义了一些预处理指令,这些指令会影响编译器解释源代码的方式,且影响发生在程序生成目标代码之前。所有预处理指令都以#号开始。而且,一行只能出现一个预处理指令。因为C#的体系结构是现代的、面向现象的,它不再像其他较老的语言那样非常需要这些预处理指令。但有时它们非常有用,尤其是条件编译时。#define#define指令定义一个符号,这个符号由一个字符序列组成,格式如下:#define符号注意语句没有分号,在#define和符号之间可以有任意多个空格,符号一旦定义,只有换行符才能将其结束。#if和#endif#if和#endif指令可以计算一个可多个符号是否为真,主要用于条件编译多条代码。如果符号已定义,那测试值为真,否则为假。因此如果用#def

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论