快精灵印艺坊 您身边的文印专家
广州名片 深圳名片 会员卡 贵宾卡 印刷 设计教程
产品展示 在线订购 会员中心 产品模板 设计指南 在线编辑
 首页 名片设计   CorelDRAW   Illustrator   AuotoCAD   Painter   其他软件   Photoshop   Fireworks   Flash  

 » 彩色名片
 » PVC卡
 » 彩色磁性卡
 » 彩页/画册
 » 个性印务
 » 彩色不干胶
 » 明信片
   » 明信片
   » 彩色书签
   » 门挂
 » 其他产品与服务
   » 创业锦囊
   » 办公用品
     » 信封、信纸
     » 便签纸、斜面纸砖
     » 无碳复印纸
   » 海报
   » 大篇幅印刷
     » KT板
     » 海报
     » 横幅

第九章 方式[《.net框架程序设计》读书笔记]

第九章 方式




一、 实例构造器

1、 前面提到用new操作符创建对象时的三部曲:

l 为对象分配内存

l 初始化对象的附加成员(方式表指针和SyncBlockIndex)

l 调用实例构造器初始化实例状态

在分配内存时,系统将所有内存位置均置为0值,这就是为什么字段初始化而未赋值时均为0或null值。



不调用实例构造器的情况:

l 调用Object.MemberwiseClone()方式创建实例(分配内存;初始化附加成员;将源对象字节拷贝到新创建的对象)

l 反序列化对象时

2、 为避免为实例字段产生过多的构造器代码,应避免在声明字段时为字段符初值,而是在无参构造器中为它们符初值,在其他重载的构造器中调用无参构造器。



3、 值类型实例构造器

l C#编译器不会自动调用其构造器,必须显式调用构造器才能起作用

l C#编译器不答应为值类型定义无参实例构造器(下面会介绍可以定义无参类型构造器)

l 不能为结构中的字段在声明的同时赋初值,可通过定义带参构造器的方法进行

l 必须在结构的构造器中为所有字段赋初值

二、 类型构造器

1、 类型构造器的一些限制:

l 不能带任何参数

l 类型构造器总为私有的,不能用其他访问修饰符

2、类型构造器被调用的时机:

l 第一个实例被创建,或者类型的第一个字段或成员第一次被访问之前

l 非继续静态字段被第一次访问之前

类型构造器在类型的生命周期中只被调用一次;

3、一些限制:

l 若类型构造器中抛出非常,则该类型变成不可访问,访问其中的任何字段或方式均会抛出System.TypeInitializationException非常

l 类型构造器只能访问类型的静态字段

l 类型构造器不应该调用基类型的类型构造器,因静态字段并非继续而是编译时静态绑定

三、 操作符重载

1、 操作符重载

C#中对操作符重载的一些限制:

l 必须声明为public static

l 必须有一个参数为操作符所属类型

l 不能改变操作符原始定义的引数个数

l 若定义了true操作符也必须同时定义false操作符,二者都必须返回bool值

l ++、--操作符必须返回其所隶属之类型的一个实例

l 可被重载的一元操作符:+、-、!、~、++、--、true、false

l 可被重载的二元操作符:+、-、*、/、%、!、^(异或)、<、>、<<、>>、==、!=、<=、>=

l 不答应被重载的操作符:&&、||、=、?:、+=、-=、/=、%=、|=、^=、<<=、>>=,实际上其中一些“复式操作符”在二元操作符被重载后自动生成,而不能显式定义

l 必须成对重载的操作符:(== ,!=)、(<,>)、(<=,>=)

l ++、--操作符重载时不能区分其为前置或后置的

2、 操作符重载与语言互操作性

编译器会为重载的操作符生成一个特别名称的方式,如+(加)操作符生成op_Addition()方式,并为该方式的定义条目上加上specialname标记。当某种语言不能进行操作符重载时,可以直接定义具有该特别名称的方式,以在其他语言中调用;或直接调用具有该特别名称的方式以适应某种语言不能解析操作符的限制。如:vb中不能重载操作符,可显式定义op_Addition()方式以在C#中调用;C#中定义的+操作符不能被VB识别,可显式调用op_Addition()方式获得同样的功能。

四、 转变操作符

转变操作符的一些限制:

l 必须为public static

l 必须指定要害字implicit或explicit,原则为:从本类型转变为其他类型使用implicit,将其他类型转变为本类型用explicit,不能都使用implicit



五、 方式参数

1、 引用参数

l 缺省情况下为值传递

l 标志为out的参数,在调用方式前不必初始化,但返回之前必须赋值,没有被初始化的参数是不能被使用

l 标志为ref的参数,在调用方式前必须初始化,否则触发编译错误

l 可以使用ref或out来进行方式的重载,但不能通过区分ref和out来重载方式

l 按引用方法传递的变量(实参)必须和方式声明的参数(形参)类型完全一样,否则触发编译错误。

2、 可变数目参数

使用params要害字及对象数组的方法指定可变参数序列。一些限制:

l 只有方式的最后一个参数才能使用可变数目参数



六、 虚方式

1、 虚方式的调用机理

CLR使用以下两个IL指令调用方式:

u call 根据类型(即引用的静态类型、声明类型)来调用一个方式

u callvirt 根据对象(即引用的动态类型、实际类型)来调用一个方式

对于虚方式使用call来调用的情况有:

l base.虚方式(),

l 密封类型引用虚方式,因为没有必要检验密封类型的实际类型

l 值类型,避免被装箱

使用callvirt调用非虚方式的情况:

l 应用变量为null时,使用callvirt才会抛出System.NullReferenceException非常,而call不会抛出

无论call或callvirt调用方式,均会有一个隐含的this指针作为方式的第一个参数,它指向正在操作的对象

2、 虚方式的版本控制:

用下面的例子说明:

using System;



class BaseClass

{

public void NonVirtualFunc()

{

Console.WriteLine("Non virtual func in base class");

}



public virtual void VirtualFunc()

{

Console.WriteLine("Virtual func in base class");

}

}



class DevicedClass : BaseClass

{

//若不使用new 要害字则编译器会有warning:

//“DevicedClass.NonVirtualFunc()”上要求要害字

//new,因为它隐藏了继续成员“BaseClass.NonVirtualFunc()”

public new void NonVirtualFunc()

{

Console.WriteLine("Non virtual func in deviced class");

}

//若不添加要害字override或new,则编译器会有warning:

//“DevicedClass.VirtualFunc()”将隐藏继续的成员“BaseClass.VirtualFunc()

//”。若要使当前成员重写该实现,请添加要害字 override。否则,添加要害字

//new。

public override void VirtualFunc()

{

Console.WriteLine("Virtual func in deviced class");

}

}



class TestClass

{

public static void Main()

{

//派生类实例调用 非虚 及 虚函数

DevicedClass dc = new DevicedClass();

dc.NonVirtualFunc();

dc.VirtualFunc();



//基类实例调用 非虚 及 虚函数

BaseClass bc = new BaseClass();

bc.NonVirtualFunc();

bc.VirtualFunc();



//指向派生类实例的基类引用 调用 非虚 及 虚函数

BaseClass bc1 = dc;

bc1.NonVirtualFunc();

bc1.VirtualFunc();

}

}



/*

在虚函数上使用要害字override的运行结果:

Non virtual func in deviced class

Virtual func in deviced class

Non virtual func in base class

Virtual func in base class

Non virtual func in base class

Virtual func in deviced class

*/



/*

在虚函数上使用要害字new的运行结果

Non virtual func in deviced class

Virtual func in deviced class

Non virtual func in base class

Virtual func in base class

Non virtual func in base class

Virtual func in base class

*/

由上可见:new 和 override在派生类中协调版本的控制,在第七章中已经看到oeverride只能用于virtual方式,new则可用于非虚或虚方式,以实现隐藏基类中的同名方式。在虚函数上使用override,重写了基类的方式,并无隐藏,这也就实现了多态。我们可设想这样的结论:new使用call指令调用静态类型的方式,而override使用callvirt指令调用动态类型的方式。

希望这个例子对您的理解有所帮助。




返回类别: 教程
上一教程: .net下模仿不同身份登陆以获取不同权限
下一教程: asp.net高级教程(三)---实战篇

您可以阅读与"第九章 方式[《.net框架程序设计》读书笔记]"相关的教程:
· .net框架程序设计读书笔记二(Microsoft .net 框架开发平台体系架构)
· 第十二章 委托[《.net框架程序设计》读书笔记]
· 第十一章 事件[《.net框架程序设计》读书笔记]
· 第十四章 数组[《.net框架程序设计》读书笔记]
· 前言[《.net框架程序设计》读书笔记]
    微笑服务 优质保证 索取样品