C#5-属性-索引器-异常处理_第1页
C#5-属性-索引器-异常处理_第2页
C#5-属性-索引器-异常处理_第3页
C#5-属性-索引器-异常处理_第4页
C#5-属性-索引器-异常处理_第5页
已阅读5页,还剩25页未读 继续免费阅读

下载本文档

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

文档简介

第五节属性、索引器、异常处理目标理解属性及其不同的类型、实现理解和使用索引器属性是类、结构和接口的成员。它们通过存取子(Accessor)提供读取、写入或计算私有(Private)字段值的弹性机制。存取子将属性存取子设定为get、set或get/set。默认情况下[存取子]选项设定为get/set。存取子选项说明get读取或计算属性并传回属性和型别值。如果选择此选项,属性便是只读的。set当对属性指派值时,会以提供新值的自变量来叫用set存取子。如果您选择了此选项,则属性是唯写的。get/set选择此选项时,属性将同时包含get和set存取子。这是一个读取写入属性。修饰符属性可以加入下列修饰符之一。static、virtual和abstract修饰符是彼此互斥的。修饰符说明无没有额外的修饰符Static属性属于该类本身而非一个特定的对象。Virtual属性可以在子类中重写Abstract属性是抽象类(AbstractClass)的成员。属性简介3-1封装把一些不重要的细节隐藏起来,这样你可以集中精力处理那些重要的内容。但封装很难被掌握,一个典型的封装误用是盲目地把公有字段转为私有字段。例如在上面的例子中,程序定义了一个私有字段hour和SetHour函数和GetHour函数,而不是定义一个公有的hour字段。如果GetHour函数只是返回私有字段的值而SetHour函数只是设置私有字段的值的话,那么你除了使Time类更难使用外,你不会得到任何好处。

structTime{

publicintGetHour()

{

returnhour;

}

publicvoidSetHour(intvalue)

{

hour=value;

}

privateinthour,minute,second;}staticvoidMain(){

Timelunch=newTime();

lunch.SetHour(12);

Console.WriteLine(lunch.GetHour());}属性简介3-1如果字段是公有的,那使用起来是简单的但如果你使用公有字段的话,你会失去控制权

要简化而不是简单structTime{

publicintHour;

publicintMinute;

publicintSecond;}staticvoidMain(){

Timelunch=newTime();

lunch.Hour=30;

lunch.Minute=12;

lunch.Second=0;

}解决的办法可以把get和set函数组合成一个简单的属性。属性的声明包括一个可选的访问修饰符(在例子中是public)、返回值(int)、属性的名字(Hour)和一个包含get和set语句的属性体。注意:属性没有括号,因为属性不是函数。属性的命名规则应符合一般的命名规则,即公有的使用PascalCase规则,而非公有的使用camelCase规则。structTime{

...

publicintHour

//没有(),是H而不是h

{

get{...}

set{...}

}

privateinthour,minute,second;}Timelunch=newTime();...lunch.Hour=12;...Console.WriteLine(lunch.Hour);get语句当读一个属性的时候,属性的get语句自动运行。get语句必须返回一个有确定类型的值。属性的返回值不能是void(从这里可以推断出字段的类型也不能是void)。这get语句必须包含一个完整的return语句(retun;这种形式是错误的)。get语句可以在retun语句前包含任何其他的语句,但return语句不能省略。注意:get和set不是关键字,可以在任何地方包括get/set语句中声明一个局部变量、常量的名字是get或set,但最好不要这样做。

必须返回一个有确定类型的值

功能上就像一个“get函数”structTime{

...

publicintHour

{

get

{

returnhour;

}

...

}

privateinthour,minute,second;}Timelunch=newTime();...Console.WriteLine(lunch.Hour);//请注意,get和set不是关键字set语句当写一个属性的时候,属性的set语句自动运行。在上面的例子中,Time结构类有一个整型属性Hour,所以赋给这个属性的值必须是一个整型值。把一个整型值12赋给了lunch的Hour属性,这个语句会自动调用属性的set语句。set语句是通过value标识符来获得属性的赋值的。例如,如果12被赋给了Hour属性,那么vaue的值就是12。注意:value不是一个关键字。value只是在set语句中才是一个标识符。你可以在set语句外的任何语句声明value为一变量的名字。通过value标识符来进行赋值的可以包含任何语句(甚至没有语句)structTime{

...

publicintHour

{

...

set{

if(value<0||value>24)

thrownewArgumentException("value");

hour=value;

}

}

privateinthour,minute,second;}Timelunch=newTime();...lunch.Hour=12;只读属性一个属性可以不必同时声明get语句和set语句。可以只声明一个get语句。在这种情况下,属性是只读的,任何写的操作都会导致错误。任何写操作都会导致错误

就像一个只读字段structTime{

...

publicintHour

{

get

{

returnhour;

}

}

privateinthour,minute,second;}Timelunch=newTime();...lunch.Hour=12;//错误...lunch.Hour+=2;//错误只写属性一个属性可以不必同时声明get语句和set语句。你可以只声明一个set语句。在这种情况下,属性是只写的,任何读的操作都会导致错误。任何读操作都是错误的structTime{

...

publicintHour

{

set{

if(value<0||value>24)

thrownewOutOfRangeException("Hour");

hour=value;

}

}

privateinthour,minute,second;}Timelunch=newTime();...Console.WriteLine(lunch.Hour);//错误...lunch.Hour+=12;//错误readonlyvs.constvs.getreadonly和const都是用来标识常量const可用于修饰class的field或者一个局部变量;而readonly仅仅用于修饰class的field。const常量的值必定在编译时就已明确并且恒定的;而readonly常量其值可以在运行时编译.const常量必须在声明的同时对其进行赋值;而readonly常量则可以根据情况选择在声明的同时对其赋予一个编译时确定并恒定的值,或者将其值的初始化工作交给实例构造函数完成。const常量属于类级别而不是实例对象级别并且它不能跟static结合一起使用,该常量的值将由整个类的所有实例对象共同分享readonly常量既可以是类级别也可以是实例对象级别的,这取决于它的声明以及初始化工作怎么实施。readonly可以与static结合使用,用于指定该常量属于类级别,并且把初始化工作交由静态构造函数完成能被const修饰声明为常量的类型必须是以下的基元类型:sbyte,byte,short,ushort,int,uint,long,ulong,char,float,double,float,bool,decimal,string。object,数组(Array)和结构(struct)不能被声明为const常量。一般情况下,引用类型是不能被声明为const常量的,不过有一个例外:string。readonlyvs.constvs.get当读一个属性的时候,属性的get语句自动运行。get语句必须返回一个有确定类型的值。属性的返回值不能是void(从这里可以推断出字段的类型也不能是void)。这get语句必须包含一个完整的return语句(retun;这种形式是错误的)。get语句可以在retun语句前包含任何其他的语句,但return语句不能省略。class

Customer

{

public

Customer(string

name,

int

kind)

{

m_Name

=

name;

m_Kind

=

kind;

}

public

const

int

NORMAL

=

0;

public

const

int

VIP

=

1;

public

const

int

SUPER_VIP

=

2;

private

string

m_Name;

public

string

Name

{

get

{

return

m_Name;

}

}

private

readonly

int

m_Kind;

public

int

Kind

{

get

{

return

m_Kind;

}

}

public

override

string

ToString()

{

if(m_Kind

==

SUPER_VIP)

return

"Name:

"

+

m_Name

+

"[SuperVip]";

else

if(m_Kind

==

VIP)

return

"Name:

"

+

m_Name

+

"[Vip]";

else

return

"Name:

"

+

m_Name

+

"[Normal]";

}

}

索引器索引器(Indexer)是C#引入的一个新型的类成员,它使得对象可以像数组那样被方便,直观的引用。索引器非常类似于属性,但索引器可以有参数列表,且只能作用在实例对象上,而不能在类上直接作用。索引器没有像属性和方法那样的名字,关键字this清楚地表达了索引器引用对象的特征。和属性一样,value关键字在set后的语句块里有参数传递意义。索引器有5种存取保护级别,和4种继承行为修饰,以及外部索引器。索引器不能为静态(static).语法:[访问修饰符]数据类型

this[数据类型标识符]{ get{}; set{};}classMyClass

{

publicobjectthis[intindex]

{

get

{

//取数据

}

set

{

//存数据

}

}

}

索引器的参数“索引”的特征使得索引器必须具备至少一个参数,该参数位于this关键字之后的中括号内。索引器的参数也只能是传值类型,不可以有ref(引用)和out(输出)修饰。参数的数据类型可以是C#中的任何数据类型。C#根据不同的参数签名来进行索引器的多态辨析。中括号内的所有参数在get和set下都可以引用,而value关键字只能在set下作为传递参数。索引器例1classstu{ privatestringname; privateintage; privatestring[]tel=newstring[3];

publicstringthis[intindex] {get { returntel[index]; } set { tel[index]=value; } }

publicstu(stringname,intage,string[]tel) { =name; this.age=age; for(inti=0;i<tel.Length;i++) {this.tel[i]=tel[i]; } }

publicvoiddis() { Console.WriteLine("yournameis{0}",); Console.WriteLine("yourageis"+this.age); for(inti=0;i<tel.Length;i++) { Console.WriteLine(this.tel[i]); } }

publicstringName { get { ; } set { =value; } }

publicintAge { get { returnthis.age; } set { this.age=value; }}}publicclassMainClass{ publicstaticvoidMain() { string[]b=newstring[3]; b[0]="abc"; b[1]="123"; b[2]="325"; stua=newstu("clm",12,b); a.dis(); stub1=newstu("lm",121,b); b1.dis(); b1[0]="111"; b1.dis(); }}索引器例2classClass1{ string[]s_name=newstring[8]; publicstringthis[intnIndex]{ get { returns_name[nIndex]; } set { s_name[nIndex]=value; } }classTest { staticvoidMain(string[]args){ Class1t1=newClass1(); for(inti=0;i<6;i++) t1[i]=Console.ReadLine();

for(inti=0;i<6;i++)

Console.WriteLine(t1[i]); } } }}索引器例3classIndexerClass{privateint[]myArray=newint[100];publicintthis[intindex]//Indexerdeclaration{get{//Checktheindexlimits.

if(index<0||index>=100)

return0;

else

returnmyArray[index];

}set{if(!(index<0||index>=100))

myArray[index]=value;

}}}publicclassMainClass{publicstaticvoidMain(){IndexerClassb=newIndexerClass();

//Calltheindexertoinitializetheelements#3and#5.b[3]=256;b[5]=1024;for(inti=0;i<=10;i++){Console.WriteLine("Element#{0}={1}",i,b[i]);}}}c#中构建异常处理

异常是程序运行中发生的错误异常处理是程序设计的一部分在c#中异常处理是通过Exception基类进行的可以创建自己的异常类,但这个类必须是继承自Exception基类异常将导致不完善或者不需要的结果,因此在程序设计中需要处理异常。异常也可以是象“IndexOutOfBounds”这样的错误,这个错误表示程序试图访问数组中部存在的元素;比如数组最大元素为100,当试图访问元素101时就将会发生这样的错误如果发生的异常不是内建的,需要创建自己的异常类,当然这个类时继承自Exception基类。C#的异常处理所用到关键字

try

用于检查发生的异常,并帮助发送任何可能的异常。

catch

控制权更大的方式处理错误,可以有多个catch子句。

finally

无论是否引发了异常,finally的代码块都将被执行。

throw

用于引发异常,可引发预定义异常和自定义异常。C#异常处理的格式try{

//程序代码块;}catch(Exceptione){

//异常处理代码块;}finally{

//无论是否发生异常,均要执行的代码块;}一个除数和零的简单例子:publicclassDivisorIsZero{privatestaticvoidMain(){intdividend=10;intdivisor1=0;intdivisor2=5;intDivideValue;try{DivideValue=dividend/divisor1;

//(1)DivideValue=dividend/divisor2;//(2)System.Console.WriteLine("DivideValue={0}",DivideValue);//(3)这一行将不会被执行。}catch{System.Console.WriteLine("传递过来的异常值为:{0}",e);}finally{System.Console.WriteLine("无论是否发生异常,我都会显示。");}}}C#的异常处理

(1)行被执行则会抛出一个异常,如果没有catch语句,程序会异常终止,使用不带参数的catch子句,则可以捕获任意类型的异常。

如果将(1)行注释掉,启用(2)行,这意味该程序运行时不会出现异常,从输出可知,finally代码块仍将被执行。C#的异常处理可以给try语句提供多个catch语句,以捕获特定的异常,如上例中:0作为除数则会引发DivideByZeroException类型的异常,上例中的catch语句可以作如下修改:

catch(DivideByZeroExceptione)子句只能捕获特定的异常,try内的程序代码可能还会产生其它的异常,这些异常只能由catch(Exceptione)来捕获。catch(DivideByZeroExceptione){

System.Console.WriteLine("零不能作为除数!异常值为:\n{0}",e);}catch(Exceptione){

System.Console.WriteLine("并非\''零作为除数引发的异常\"!异常值为:\n{0}",e);}System名称空间中常用的异常类System名称空间中常用的异常类异常类名称

简单描述MemberAccessException

访问错误:类型成员不能被访问ArgumentException

参数错误:方法的参数无效ArgumentNullException

参数为空:给方法传递一个不可接受的空参数ArithmeticException

数学计算错误:由于数学运算导致的异常,覆盖面广。ArrayTypeMismatchException数组类型不匹配DivideByZeroException

被零除FormatException参数的格式不正确IndexOutOfRangeException

索引超出范围,小于0或比最后一个元素的索引还大InvalidCastException

非法强制转换,在显式转换失败时引发MulticastNotSupportedException不支持的组播:组合两个非空委派失败时引发NotSupportedException调用的方法在类中没有实现NullReferenceException引用空引用对象时引发

温馨提示

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

评论

0/150

提交评论