购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP


陷阱09
误入歧途
——传递派生类产生的陷阱

1.陷阱产生的场景

在面向对象的语言中,如果类B继承自类A,那么B类是A类的派生类(或子类),A类是B类的基类(或超类)。派生类和基类之间是“is-a”的关系。在C#语言中有个特点,所有的类最终都是派生自System.Object类,因此可以说所有的类都与System.Object类存在“is-a”的关系。

例4.9 传递派生类产生的陷阱(光盘位置:光盘\MR\Instance\4\09\UseChildClass),该实例的主要分析过程如下。

由于派生类和基类之间的“is-a”关系,所以在参数传递过程中,可以将派生类的对象传递给基类的引用。例如,类B继承自类A,代码如下:

在参数传递中,可以用A类型的参数接收B类型的对象,代码如下:

上面的代码编译完全正常,这说明可以将派生类对象传递给其基类类型的参数。而System.Object类是所有类型的基类(包括string类型),那么在参数传递中能否用System.Object类型的参数接收string类型呢?代码如下:

在上面的代码中,TransferClass类的TransferMethod方法中包含一个System.Object类型的参数。下面是调用TransferMethod方法的代码:

在上面的代码中,首先创建一个TransferClass类型的对象TransferObject,其次将string类型的变量testStr传入TransferObject对象的TransferMethod方法。按照上面介绍的内容推理,这段代码不会有问题,可是编译时却出现如图4.16所示的错误。

图4.16 编译错误提示

2.陷阱的分析

按照派生类与基类之间的“is-a”关系,不应该出现这些错误信息,因为任何C#的数据类型都是一个object,任何类型最终都是继承自object。这其中也应该包括string对象。那为什么string对象不能隐式地转换成object类型呢?经过进一步分析发现,上面实例中的错误与TransferMethod方法中使用的ref参数修饰符有直接关系。ref修饰符使得TransferMethod方法中的代码能够改变该变量的值,即传入的参数值和传出的参数值可能不相同,例如,可以将传入的string类型的变量转换为TransferClass类型:

在上面的代码中,当调用方法时传递一个字符串,在执行TransferMethod方法后返回一个TransferObject类型。进一步说在TransferMethod方法中可以将传入的变量转换为任意类型,这样调用程序在接收该方法的返回值时,会由于变量类型的不确定性导致错误发生。这是调用程序不希望看到的。所以C#在调用方法时,强制要求只能使用正确的参数类型,从而避免这种问题。

3.陷阱的解决方法

针对上面的情况,该陷阱的解决方法有以下两种。

❏ 将TransferMethod方法中的参数类型设置为string类型,这样在传入string类型的变量时就不会出现错误了。

❏ 首先将string类型的变量转换为object类型,再将object类型的变量传入TransferMethod方法,代码如下:

说明

传递到ref参数的变量必须首先初始化,然后才能传入方法中。这与out关键子不同,out关键字修饰的参数在传递之前不需要显式初始化。 Vwt/Nf9G/fMLTNgFDLSmhSHeVTfDisSQX5LfvO5BO2nahPFfdhOW0g6m7IE1f5h0

点击中间区域
呼出菜单
上一章
目录
下一章
×