.NET框架程序设计(修订版)-- 笔记(四)

第Ⅳ部分 基本类型

第十二章     文本处理

12.1字符

       一个字符由一个System.Char结构(值类型)实例表示。它提供两个常数字段:MinValueMaxValue

       可以调用Char的静态方法GetUnicodeCategory返回一个System.Globalization.UnicodeCategory枚举值来判断字符的类型。

       GetNumericValue返回一个字符的对应的数值形式。

12.2System.String类型

       12.2.1创建字符串

              不能使用new操作符来创建String对象。不建议使用\n等转义符,应该使用System.Environment提供的方法。尽量少的使用+操作符来拼接字符串,因为它会在要执行垃圾收集的托管堆上创建多个字符串对象。

       12.2.2字符串的恒定性

              String对象的最重要特性便是恒定性,也就是一个字符串一旦被创建,我们就不可能再将其变长、变短、或者改变其中任何的字符。

       12.2.3字符串比较

              P.256-25712.1有关字符串比较的方法。

              使用CompareInfo类的方法,进行排序比较等,相对于String类中的方法拥有更多的控制。

              字符串比较损伤系统性能。

       12.2.4字符串驻留

              String s = “Hello”;

              Console.WriteLine(Object.ReferenceEquals(“Hello”,s));

              将返回True

              String s1 = “Hello”;

              String s2 = “Hel”;

              Srring s3 = s2+“llo”;

              ReferenceEquals将返回False

              Equals将返回True

              S”Hello”运行时,CLR会在第一次碰到的时候在散列表中创建”Hello”,当第二次碰到时,会将引用直接指向刚刚创建的散列表。S3动态创建的将是一个新的对象。

              将相同字符集的动态字符变为托管堆中的一个字符串对象的话,应用程序需要的对象会大大减少,有利于系统性能的提升。可以使用Intern方法(查找后如没有则创建并返回引用)、IsInterned方法(查找后不创建返回null

        12.2.5字符串池技术

              CLR帮我们在元数据中只写入一次相同的文本常量字符串,这样可以免去多个相同字符串带来的元数据文件膨胀。

        12.2.6查看字符串中的字符

              P.266-26712.2查看字符串中字符的一些方法。

              使用代理项可以使Unicode可以表示较多字符,包括中文等。System.Globalization.StringInfo类型的静态方法GetTextElementEnumerator来枚举字符创中包括的所有抽象Unicode字符。

        12.2.7其他字符串操作

              包括拷贝、InserRemove等等其他方法,返回的都是新字符串,因为是字符串恒定不变的。

12.3高效地动态创建字符串

       System.Text.StringBulider对象,在内部指向一个Char结构数组的字段。在构建完成后可以使用ToString()方法转换为一个String对象。

       12.3.1构造StringBulider对象

              StringBulider sb = new StringBulider(“…”);

              内部维护的字段:①最大容量,可以容纳字符的最大长度,默认20亿;②容量,维护的字符数组字段的长度。③字符数组。

        12.3.2StringBulider的成员

              为了获得更高的性能,不会分配新对象,不会保证线程安全。

              P.273-27412.4StringBulider的成员

12.4获取对象的字符串表达形式

        重写ToString方法。

        12.4.1特定格式与语言文化

              ToString()方法中的IFormatProvider接口规范,默认返回当前线程的System.Globalization.CultureInfo类型实例。

        12.4.2将多个对象格式化为一个字符串

              使用静态的Format方法,StringBulider使用AppendFormat方法,工作原理类似。

        12.4.3提供自定义格式化器

12.5通过解析字符串获取对象

              大部分类型都提供了解析字符串的静态方法Parse。参数NumberStyles(数字类型)是一个位标记枚举类型,标识可能在字符串中出现的字符形式。

        P286-28712.5NumberStyles类型定义的位符号

        P28712.6NumberStyles类型定义的位组合符号

        P28912.DateTimeStyles类型定义的位符号

12.6编码:字符与字节之间的转换

              System.Text.Encoding的静态属性,Default取决于用户计算机,GetEncoding(“”)可以填入需要的编码对象来构建。

        P29312.8继承自Encoding类的属性

        P29612.9继承自Encoding类的方法

        12.6.1字符与字节的编码/解码流

        12.6.2Base-64字符串编码与解码

              使用System.Convert类型提供的一些静态方法来实现FromBase64StringFromBase64CharArry

第十三章     枚举类型与位标记

13.1枚举类型

       好处:①使得程序更容易编写、阅读和维护;②枚举类型是强类型。

       枚举类型就是一个定义了一组常数字段的结构而已,编译后存放在生成模块的元数据中,并通过反射来访问。

       静态方法GetUnderlyingType(Type enmuType)返回用于保存枚举类型实例值的基础类型(underlying type),使用基元类型定义基础类型 enmu Color:byteToString()方法会默认调用Fromat方法,允许我们传递枚举值的数值形式。GetValues允许我们获取一个枚举中定义的所有符号。GetName方法返回枚举符号。Parse方法将文本符号转换为一个枚举实例。IsDefined判定数值对于某个枚举类型是否合法。枚举类型应该定义在需要它的类型的同一层次上,而不是该类型中。

13.2位标记

       在需要作为位标记的枚举上定义特性[Flags][FlagsAttribute],可以将枚举数值看做是一组标记,而非一个单独的数值。

第十四章     数组

数组总是分配在托管堆上的引用类型,并且应用程序中的数组变量包含的是一个指向数组的引用,而非数组本身。

CLS要求所有的数组都是0基数。

我们应该尽可能的使用一维0基数组,有称作SZ数组(single-dimensionzero-based数组),或者向量(vector),性能最好。

多维数组:String[,,,,,…] = new String[2,5,6,8,10,20…];

交错数组:数组中包含数组。

14.1所有数组的基类:System.Array

       P.312-313-31414.1System.Array的成员

14.2数组的转型

       Array.Copy方法:①装、拆箱;②拓宽CLR基元类型;

14.3数组的传递与返回

14.4创建下限非0的数组

       CreateInstance方法动态创建。

14.5快速数组访问

       Fixed(Int32* element=&arr[0]){……}

       只能用于部分类型,不包括String

14.6重新调整数组长度

       使用CreateInstance方法

第十五章     接口

15.1接口与继承

       接口与基类设计指导:

    IS-A(基类)与CAN-DO(接口)关系

    易用性,基类比较灵活,接口必须实现其全部成员

    一致的实现

    版本

15.2设计支持插件组件的应用程序

       创建一个程序集,然后在其中定义接口,接口的方法将用于应用程序和插件组件的通信机制

       创建一个单独的程序集用于包含我们的应用程序所使用的其他类型

       插件开发人员会在他们的程序集中定义自己的类型

15.3使用接口改变已装箱值类型中的字段

15.4实现多个有相同方法的接口

       接口1.a();接口2.a();

15.5显式接口成员实现

       提供类型开全,减少值类型的装箱操作。应尽量谨慎的使用,会带来代码的混乱及编写的麻烦。

第十六章     定制特性

16.1使用定制特性

       它们仅仅是为目标元素提供关联附加信息的一种方式。C#允许我们将特性引用于:程序集、模块、类型、字段、方法、方法参数、方法返回值、属性、事件。指定前缀可消除二义性,如[assembly:MyAttribute(1)](应用于程序集)、[type:MyAttrbute(3)](应用于类型)等,P.347-348。一个特性就是类型的一个实例,该类型必须有一个工友构造器来创建它的实例。

16.2定义自己的特性

       特性是一个继承自System.Attribute的类型。

       [AttributeUsage(AttributeTargets.……,Inherited = true/false)]

       AttributeTargets指定自己定义的特性可以应用在什么类型上面。

       Inherited表示特性是否应该应用于派生类或者派生方法上。

       AllowMultiple表示特性在同一个类型上是否可以多次调用。

       如果没有使用AttributeUsage,默认为:它可以应用于所有的目标元素;它在一个目标元素上只可以应用一次;它可以被继承。

16.3特性构造器与字段/属性的数据类型

16.4检测定制特性

       P.35616.1System.Attribute类的一些方法

              IsDefined如果有至少一个Attribute的派生类应用在目标元素上,返回true

              GetCustomAttributes应用在目标元素上的特性实例数组,通常用于AllowMultiple=true

              GetCustomAttribute返回一个指定的、应用在目标元素上的特性,用于AllowMultiple=false

       System.Reflection命名空间中定义的一些类型允许我们查看一个模块中的原数据内容。这些类型也都提供了IsDefinedGetCustomAttributes方法。只有Attribute提供了GetCustomAttribute

16.5特性实例间的匹配

       充写Match方法,对实例进行类型比较(this与传递进来的)。

16.6伪定制特性(pseudo-custom attribute)

       GetCustomAttributes等方法无法检测Serializable等这些常用特性,微软对其进行压缩优化,可以通过System.Type的一些只读属性来进行监测。

第十七章     委托  -- 大量编码例程

17.1认识委托(delegate)

17.2使用委托回调静态方法

17.3使用委托回调实例方法

17.4委托揭秘

       编译器会将一个委托完整的编译为一个类,包括:一个构造器、InvokeBeginInvokeEndInvoke四个方法。

       所有委托继承自MulticastDelegate类,P.37217.1MulticastDelegate中几个重要的私有字段

17.5委托史话System.DelegateSystem.MulticastDelegate

       System.MulticastDelegate(表示可以被链接在一起的委托对象)

System. Delegate。(表示单个委托对象)

目前,因为这两个类带来的困惑,微软修改了编译器,基本全部继承自System.MulticastDelegate

       17.6委托判等

              Delegate重写了ObjectEquals虚方法,MulticastDelegate又重写了DelegateEquals实现。MulticastDelegate重写的Equals方法在比较两个委托对象时会首先看它们的_target_methodPtr字段是否都指向同样的对象和方法。如果这两个字段不匹配,返回false,如果匹配,那么再看两个委托对象是否表示委托链表的头部——也就是说它们的_prev字段不为null,两个委托对象的_prev字段指示的链表有相同的长度,那么返回true,否则返回false

       17.7委托链

              每个MulticastDelegate委托的_prev用于指向另一个MulticastDelegate对象的引用。因此,可以组合成一个链表。

              使用System.DelegateCombine进行操作。

              Delegate.Combine(DG1,DG2);组合两个并返回DG2,它是链表的末端(先被调用)

              Delegate.Combine(DG[]);创建由数组表示的链表,0为链表尾部,并且是末端(先被调用)

              Delegate.Remove(DG,value);从链表中移除一个和value的回调目标/方法向匹配的委托,新的链表头将会被返回,并且是末端(先被调用);如果没有找到,则不执行任何操作,返回传递给它的第一个参数。

        17.8C#对委托链的支持

              C#重载了+=-=操作符调用CombineRemove方法。

        17.9对委托链调用施以更多的控制

              GetInvocationList()方法,创建一个委托数组,每个元素都是委托链上对象的一个克隆,0是尾部,第一个调用。

        17.10委托与反射

posted @ 2010-01-01 15:59  壊小子  阅读(232)  评论(0编辑  收藏  举报