第4章C#高级特性,异常,调试唐大仕dstang2000@263.net本章内容4.1程序的组织4.2委托与事件4.3操作符重载4.4异常处理4.5Attribute4.6C#语言中的其他成分4.7程序的调试4.1程序的组织名字空间程序的逻辑组织嵌套类型类中嵌套类型程序集程序的物理组织名字空间1.名字空间的概念逻辑划分;避免名字冲突2.名字空间的声明namespacexxx.xxxx{}可嵌套3.名字空间的导入usingxxx.xxxx;4.使用别名using别名=名字空间或类名;NamespaceUsing.cs嵌套类型嵌套类型的概念类型中的类型classA{publicclassB{publicstructC{}}}newA.B.C();嵌套类型的可访问性受各个层次的限制NestedAccessibility.cs程序集模块(module)程序集(assembly)在VS.NET上引用程序集在项目上点右键,添加引用csc/target:mod/out:Add.modAdd.cscsc/target:mod/out:Multi.modMulti.csal/target:library/out:MyLibrary.dllAdd.modMulti.modcsc/target:exe/out:MyClient.exe/reference:MyLibrary.dllMyClient.csAdd.csMulti.csAdd.modMulti.modMyLibrary.dllMyClient.exeMyClient.cs4.2委托与事件大致上:委托-------函数指针事件-------回调函数委托委托的声明publicdelegatedoubleMyDelegate(doublex);委托的实例化MyDelegatedd2=newMyDelegate(obj.myMethod);委托的调用委托变量名(参数列表)d2(8.9)DelegateIntegral.cs委托示例DelegatePlotFun.cs委托的合并委托的合并----多播MultiCastDelegate一个委托实例中可以“包含”多个函数调用委托,就是调用其中多个函数多个函数间的先后顺序是没有意义的运算符+-+=-=动态地增减其中的函数提高了程序的灵活性DelegateMultiTest.csDelegate温度.cs委托的转换与相等委托的转换按声明的名称判断以下两个不能互相转换或加减delegatevoidD(inta);delegatevoidE(inta);委托的相等按内容(即其中“包含的函数”)来判断DelegateEquals.cs事件事件的声明publicevent委托名事件名;事件的注册与移除事件名+=或-=在事件所在类的外面,只能用以上两个运算符事件的发生事件名(参数列表)相当于回调所注册的函数事件与委托的关系事件有点像委托类型的实例事件一定有相关的委托类型与委托实例一样,事件也“包含”多个函数事件的运算符受更多限制(+=或-=)事件比委托实例更复杂:事件存取器修饰符event委托类型名事件名{add{e+=value;}remove{e-=value;}}EventButtonForm.cs使用事件的例子网络爬虫程序中通知调用者下载开始、结束及下载进度EventWhenDownload.cs4.3操作符重载操作符重载的概念操作符有时比方法名更直观如两个复数用a+b比a.Add(b)更直观但要慎用操作符重载有一些限制如成对,如类型要求,如有的不能重载更详细的内容,请参见文档操作符的声明一元操作符声明的形式如下:publicstatic类型operator一元操作符(类型参数名){……}二元操作符声明的形式如下:publicstatic类型operator二元操作符(类型参数名,类型参数名){……}类型转换操作符声明的形式如下:publicstaticimplicitoperator类型(类型参数名){……}publicstaticexplicitoperator类型(类型参数名){……}OperatorComplex.cs4.4异常处理异常处理异常可以以两种不同的方式引发:throw语句无条件,即时的抛出异常。C#语句和表达式执行过程中激发了某个异常的条件,使得操作无法正常结束,从而引发异常。例如整数除法操作分母为零时将抛出一个异常。首先介绍一下throw语句。throw语句抛出一个异常的语法为:throwexpression带有表达式的throw语句抛出的异常是在计算这个表达式时产生的。异常由try语句来处理的try语句提供了一种机制来捕捉执行过程中发生的异常。以下是它的三种可能的形式:try-catchtry-finallytry-catch-finally异常的概念C#中的异常处理try{}catch(Exceptione){}finally{}System.Exception类publicException();publicException(strings);Message属性StackTrace属性几种常用的异常类System.OutOfMemoryExceptionSystem.StackOverflowExceptionSystem.NullReferenceExceptionSystem.TypeInitializationExceptionSystem.InvalidCastExceptionSystem.ArrayTypeMismatchExceptionSystem.IndexOutOfRangeExceptionSystem.MulticastNotSupportedExceptionSystem.ArithmeticExceptionSystem.DivideByZeroExceptionSystem.OverflowException捕获和处理异常抛出异常thrownewSomeException();捕获异常try{}catch(AExceptione1){}catch(BExceptione2){}catch(更一般的Exceptione){}finally{}注:catch{}表示捕获所有种类的异常ExceptionIndexOutOf.csExceptionSimple.cs创建用户自定义异常类从Exception或ApplicationException继承重抛异常throws;异常链接thrownewExcepiton(“msg”,e);这里e称为内部异常InnerException属性使得外部能进一步知道内部的异常原因ExceptionInner.cs算术溢出与checked对溢出进行检查对整个程序csc/checkedXXXX.cs对部分程序针对表达式:checked(表达式)及uncheckd(表达式)针对块语句:checked{……}及uncheckd{……}对溢出异常进行捕获try{}catch(OverflowExceptione){}CheckedTest.cs4.5AttributeAttribute[HelpUrl(“”)]classSomeClass{[WebMethod]voidGetCustomers(){…}stringTest([SomeAttr]stringparam1){…}}Attribute是与类、结构、方法等元素相关的额外信息,是对元信息的扩展。通过Attribute可以使程序、甚至语言本身的功能得到增强。使用系统定义的Attribute使用Attribute的一般方式在程序集、类、域、方法等前面用[]表示可以省略“Attribute”几个字母,只写xxxxx可以带参数位置参数(相当于构造方法带的参数)命名参数(域名或属性名=值)示例在Main()方法使用[STAThread]使用“过时”:AttributeObsolete.cs使用“条件”:AttributeConditional.cs在结构上、枚举上使用:StructLayout,Flag在程序集级别应用Attribute[assembly:AssemblyCompany()]自定义Attribute1.声明Attribute类2.使用Attribute类3.通过反射访问属性AttributeHelp.csAttributesareclassesAttachedtotypesandmembersAttributescanbequeriedatruntimeclassHelpUrlAttribute:System.Attribute{publicHelpUrlAttribute(stringurl){…}…}[HelpUrl(“”)]classSomeClass{…}Typetype=Type.GetType(“SomeClass”);object[]attributes=type.GetCustomAttributes();4.6C#语言中的其他成分编译预处理1.标识符声明#define定义一个标识符;#undef“取消定义”一个标识符。2.条件处理#if,#elif,#else,#endif3.信息报告#error和#warning4.行号标记#line行号文件名unsafe及指针1.unsafe用于修饰类、方法等2.fixed及指针fixed(类型*指针名=表达式)语句3.sizeof运算符sizeof(简单或结构类型名)4.stackalloc在栈上分配的内存,而不是在堆上,因此不会担心内存被垃圾回收器自动回收。UnsafeCopy.csC#AndPointersDeveloperssometimeneedtotalcontrolPerformanceextremesDealingwithexistingbinarystructuresAdvancedCOMSupport,DLLImportC#“unsafe”=alimited“inlineC”Pointertypes,pointerarithmeticUnsafecastsDeclarativepinning(fixedstatement)C#developershaveheadroomUnsafeExampleclassFileStream:Stream{inthandle;[dllimport(kernel32,SetLastError=true)]staticexternunsafeboolReadFile(inthFile,void*lpBuffer,intnBytesToRead,int*nBytesRead,Overlapped*lpOverlapped);publicunsafeintRead(byte[]buffer,intindex,intcount){intn=0;fixed(byte*p=buffer){ReadFile(handle,p+index,count,&n,null);}returnn;}}其他关键字1.lock多线程程序中,lock可以将某个对象加锁2.volatile随时可能被程序以外的其他因素所修改。域被volatile修饰时,会阻止编译器对它的优化。C#几个语法的小结类型声明类的成员类型声明类型声明是C#程序的主体,它可以位于名字空间中,也可以是嵌套的类型。类型声明