asp3.5程序设计:《C#和.NET3.5高级程序设计(第4版)》笔记4
疯狂代码 CrazyCoder/ ĵ:http:/CrazyCoder/BlogDigest/Article76606.html
;第四章 C#核心编程结构2本章对前一章进行补充,介绍了构造C#方法的细节,探讨了方法的各种关键字和方法重载的主题,之后介绍数组类型,也介绍了枚举类型、结构类型,然后详细介绍了值类型和引用类型之间区别,最后探讨了可空数据类型以及?和??运算符。4.1方法重载和参数修饰符C#中有四种参数修饰符
,分别为:(无),此时为值传递。数据的副本就会被传入函数,至于到底复制什么,取决于参数是值类型还是引用类型,前者复制值类型的本身,后者复制的是引用(指针)。
out,输出参数,若参数用out声明,则调用时也必须加上out。使用前不用赋值,函数退出时,要给参数赋值,否则编译错误。
ref,引用参数,和out类似,区别主要有:
输出参数(out)无需(不是必须,赋的值也会在后面重新赋值时覆盖)传递前初始化,退出时必须给他赋值;引用参数(ref)必须在传递前初始化,退出时可以(不是必须)改变他的值。可以看出,以上两种方式的优点就是,只使用一次方法就可以获得多个返回值!而常规方式,只能用return返回一个值!注
意,将一个值类型的参数用上述两个修饰符进行声明,不会出错,但是,没有任何意义,和第一种方式的结果是一样的,不会真的改变值类型,对于引用类型,则不同,具体看本章后面。params,参数数组。可以把可变数量的参数(相同类型)作为单个逻辑参数传给方法。需要强调的是,这种方式声明的参数数组,在调用时,可以有两种方式
,一种是传入强类型的数组(和用常规数组作为参数时一致),另一种是以逗号分割的项列表(这才是特有的方式),例如,下面的方法:
static double calculateaverage(int i,parmas double[] values){}则调用时,可以用如下两种中任意一种哦:double[] b={1,2,3};calculateaverage(100,b);//第一种方式calculateaverage(100,1,2,3);//第二种方式第二种方式时,编译器会自动将后三个参数打包成数组,作为double[]参数传入。若不用params声明,第二种方式将出错!成员重载:是指一组名称相同,参数数量(或类型)不同。关键要确保方法的每一个版本都有不同的参数组(只是返回类型不同是不够唯一的),能够保证唯一的条件是:参数个数不同参数类型不同
(int,)需要注意的是,虽然类型不同可以通过编译,但是若类型之间出现交集,看如下情形: ; ; ; ; ; ; ; ; ;static void ww(int b)
; ; ; ; ; ; ; { Console.WriteLine("test1"); }
; ; ; ; ; ; ; static void ww(uint b)
; ; ; ; ; ; ; { Console.WriteLine("test2"); }则我无论用ww(1)还是ww(-1),是没法执行第二个重载方法的,因为这两个类型之间出现交集。参数修饰符不同(out,ref,“无”等)注:这是一些显而易见的组合,对于每一种搭配,时候产生歧义,感兴趣的可以继续研究一下。4.2数组数组当然是一组相同类型的数据点。下界从0开始。new(声明数组)后,若不显示填充,则每项都给予默认值。总结一下数组的初始化方法:(1)逐个填充int[] a=new int[3];//使用此方法时,必须指定数组大小;这样才能默认填充这么多个值,此时,所有数组中值均为0,下面可以对不想是默认的项逐个赋值。a[0]=1;a[1]=2;(2)花括号初始化以下三种方式均可: ;int[]
a=new int[]{1,2,3};
int[] a=new int[3]{1,2,3};
int[] a={1,2,3};
也就是说,不需要指定数组大小,因为可以通过花括号的项来推断;new关键字是可选的。若数组大小指定了,却和花括号中项数不一致,反而出错,因此,推荐第三种,简单!在c#数组中,可以定义引用类型的数组
,
如datatable类型,string类型,甚至是object的数组,这时候,不仅需要对整个数组进行实例化,还需要对其中每一个项进行实例化,记住,每一项还需要进行实例化哦。如:object[] myobject=new object[2]; myobject[0]=10; //此项为值类型,直接赋值myobject[1]=new datatime(1988,1,3);//为引用类型,需要实例化多维数组:包括了矩形数组和交错数组。矩形数组:每一行的长度都相同的多维数组。int[,] a =new
int[1,2];交错数组:包含一些内部数组,每一个都有各自的上界。int[][] a=new int [5][3];这些数组的声明方法和初始化,有兴趣的可以查看相关资料,这里不再赘述。另外,数组可以作为参数(返回值)。4.3枚举枚举用于创建一组符号名和已知数字值的类型。定义方法:enum emptype{manager,grnut=10,contractor,}注意,最后一个逗号可以有也可以没有!默认情况下,第一个元素若没有赋值,则被默认是0,若其中任意一个没有赋值,则默认是上一个成员的数值加1,则可以推断,contractor为11。这些值不一定连续,也不一定唯一,没有限制。默认时,枚举值的存储类型为int类型,若想更改,则可以使用冒号来设置,C#支持
byte,sbyte,short,ushort,int,uint,long,ulong。使用方法:enum emptype:bytes{manager,grnut=10, contractor,}对于enum,我不经常使用,对它的用法,觉得也比较别扭。上面定义了一个emptype的枚举,但是使用时,却只能使用其中一个,可能还是对这种类型不太熟悉吧!如:emptype a=emptype.manager;若要获取枚举中的符号名名称,用a.tostring()即可,若要获取a对应的数值,必
须根据底层存数类型,进行强制转换(byte)a,这是由于,虽然emptype中的各个符号对应的是数值,但是并非真的是数值类型,因此必须转换成为数值。4.4结构结构是可以包含许多数据字段和操作这些字段的成员的用户自定义类型。结构有许多类似于类的特性,可以看成是轻量级的类类型。结构可以定义构造函数,实现接口,还包含许多属性、方法、事件以及重载运算符。但是结构无法继承。初始化一个结构体,有两种方式,一种是创建变量后,为每一个公共字段数据赋值。例如定义一个结构体: ;struct point
; ; ; ; ; ; ; {
; ; ; ; ; ; ; ; ; ; ; public int a;
; ; ; ; ; ; ; ; ; ; ; public int b;
; ; ; ; ; ; ; ; ; ; ; public void display()
; ; ; ; ; ; ; ; ; ; ; {
; ; ; ; ; ; ; ; ; ; ; ; ; ; ; Console.WriteLine("a:{0},b:{1}",a, b);
; ; ; ; ; ; ; ; ; ; ; }
; ; ; ; ; ; ;
; ; ; ; ; ; ; }则使用时:point p;p.a=1;p.b=2;p.display();另外一种方式是使用new关键字来创建变量,他会调用结构的默认构造函数(因此,结构中不允许再定义没有参数的构造函数,也就是这个系统提供的默认构造函数无法覆盖),并自动为公共字段赋予默认值。如:point p=new point();p.display();还一种方式,就是利用自定义的构造函数,这需要在定义结构时显示进行定义才可使用。4.5值类型与引用类型值类型都隐式派生自system.valuetype,从而确保所有派生类型都分配在栈上而不是垃圾回收堆。其唯一目的是重写了由system.object定义的虚方法来使用基于值而不是基于引用的语法,重写会改变定义在基类中的虚(也可能是抽
象的)方法的实现,事实上,valuetype定义的实例方法和由object定义的完全相同。由于值类型使用基于值的语法、结构,生命期可以预测,当离开定义域的范围,他就立刻从内存中移除。当用赋值运算符(=)将一种类型赋值给另外一个时,有两种情况:将一个值类型赋值给另外一个时,对字段成员逐一进行复制(对于int这样简单类型,唯一需要复制的成员就是数值,对于结构,如上point,则a,b的值都会被复制到新的结构变量中。)栈上会有这个类型的两个副本,每个都被独立操作,一个的变化,不影响另外一个。将一个引用类型赋值给另外一个时,在内存中重定向引用变量的指向。两个引用指向托管堆中的同一个对象,因此,其中一个的改变,同时会影响另外一个。包含引用类型的值类型:若在一个值类型中包含引用类型,比如结构中有一个类类型,则将这个结构赋值给另外一个时,
将会把结构中值类型进行赋值,而将结构中的引用进行复制,因此
,更改结构中的值类型不影响另外一个,而两个结构中的类其实是引用一样的,改变其中一个,必然影响另外一个结构中的类。这就是所谓的“浅复制”,还有一种称为“深复制”,即将内部引用的状态完全复制到一个新的对象中去,需要实现ICLoneable结构,之后的篇章中会讲到。按值传递和按引用传递引用类型:本章一开始就说了参数又四种类型,其中就有按值传递(无修饰符)和按引用传递(ref和out),前面说过对于一个值类型用引用传递来修饰没有任何意义,虽然不会报错,但是和按值传递没有区别,不会真的改变值类型的值。但是,对于引用类型,采用值传递和引用传递,效果是不同的!按值传递一个引用类型(如person)时,如: static void send(person p)
{
p.age=99;// 这句是有效的aspnet和net的区别
p=new person("lee",99);// 这句是无效的}
按引用传递一个引用类型(如person)时,如:
static void send(ref person p)
{
p.age=99;// 这句是有效的
p=new person("lee",99);// 这句是有效的}
前者类似于p是一个常量指针,可以访问和修改它指向的对象,但是不能更改它的指向(new)。后者类似于可变的指针,可以访问和修改它指向的对象,也可以更改它的指向,使之重新指向另外一个对象。
这个区别是在之前所有书籍中都没有介绍过的!!再简单总结一下一些遗漏的值类型与引用类型的区别:
前者不能被继承,后者可以;前者默认构造函数是系统提供的,用户不能自定义一个没有参数的构造函数,后者当然可以。
4.6可空类型.NET2.0发布后,支持一种可空类型。它就是可以表示所有基础类型的值加上null,为了定义一个可空变量类型,应在底层数据类型中添加问号(?)作为后缀进行声明。
注意,这种类型只对值类型合法,定义一个可空引用类型是不合法的(引用类型本身就可以为null!)
定义方法:
int? a=10;
int?[] b=new int?[5];
Nullable<int> c=10;
public int? getsomething()
{
}
注:?后缀记法是创建一个泛型system.nullable<T>的缩写。
可以功过hasvalue或!=运算符判断是否为空。
对于这个可空类型,可以通过value属性或直接的获取这个值(可以是空)
最后,可以使用 ??运算符,在当获取的值是null时,讲一个值赋值给这个类型,这相当于一个判定语句,当为空时附一个值,不为空时,不理睬。如:
int? somtthing()??100
如果dr.getsomtthing()返回一个空值null,则将100赋值给a,否则将dr.getsomtthing()的返回值赋值给a。 2009-10-10 16:42:58
疯狂代码 CrazyCoder/
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论