C#类中虚方法相互调用的潜在重载错误
2005-02-25 00:12
344 查看
当我们编写基类虚方法时,需要注意一个问题,就是基类中虚方法的相互调用,有可能引起派生类重载时的潜在错误隐患。当然这个错误并不是C#语言设计的缺陷,而是一个不可避免的实现而已。当然如果我们是要编写通用的组建基类,就需要注意一下了。
或许我们刚开始做OOP的时候,对于有没有方法有没有virtual根本不在乎,很多是时候我们都重写了(rewrite)了基类方法。当然在需要确定重载(override)的时候,virtual关键字限定基类方法是不可少的。那么是不时我们就可以把基类的方法都弄成virtual修饰的呢?这样虽然在大多时候没有问题,而其如果是自己重载自己的基类出问题的可能性也不大,可是如果是别人来继承基类,那么问题可能就来了。
当我们重载不确切的基类是,最好的习惯是调用以下base的同名方法,这个在控件开发时用的更加普遍。可是这个时候,如果基类之间存在虚方法调用了别的被重载的虚方法,潜在错误就出来了。看下面示例(由xingd提供,我修改):
using System;
public class Base
public class Derived : Base
public class Test
Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.
at Derived.Bar()
at Derived.Foo()
at Test.Main()
问题代码就是:
Console.WriteLine("Derived::Foo");
base.Foo();
obj = new Object();
this.Bar();
由于base.Foo()中的this.Bar()方法已被重载,所以实际执行的是Derived::Bar,而这个时候我的obj还没有初始化呢。
当然修正这个bug也很容易,就是把Base::Bar变为非虚方法就可以了。由于C#可以灵活的设置virtual来控制方法是否需要重载,所以这类问题完全是由代码的设计缺陷所引起的,而且如果由一个人来写一般是不会设计出这样的代码的,可是如果基类和派生类由不同的人来写,出这样的错误的机会可能就会更大一些。
或许我们刚开始做OOP的时候,对于有没有方法有没有virtual根本不在乎,很多是时候我们都重写了(rewrite)了基类方法。当然在需要确定重载(override)的时候,virtual关键字限定基类方法是不可少的。那么是不时我们就可以把基类的方法都弄成virtual修饰的呢?这样虽然在大多时候没有问题,而其如果是自己重载自己的基类出问题的可能性也不大,可是如果是别人来继承基类,那么问题可能就来了。
当我们重载不确切的基类是,最好的习惯是调用以下base的同名方法,这个在控件开发时用的更加普遍。可是这个时候,如果基类之间存在虚方法调用了别的被重载的虚方法,潜在错误就出来了。看下面示例(由xingd提供,我修改):
using System;
public class Base
public class Derived : Base
public class Test
Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.
at Derived.Bar()
at Derived.Foo()
at Test.Main()
问题代码就是:
Console.WriteLine("Derived::Foo");
base.Foo();
obj = new Object();
this.Bar();
由于base.Foo()中的this.Bar()方法已被重载,所以实际执行的是Derived::Bar,而这个时候我的obj还没有初始化呢。
当然修正这个bug也很容易,就是把Base::Bar变为非虚方法就可以了。由于C#可以灵活的设置virtual来控制方法是否需要重载,所以这类问题完全是由代码的设计缺陷所引起的,而且如果由一个人来写一般是不会设计出这样的代码的,可是如果基类和派生类由不同的人来写,出这样的错误的机会可能就会更大一些。
相关文章推荐
- "C#类中虚方法相互调用的潜在重载错误"相关思考
- 第十五讲:重载(实例补充之构造函数及普通方法,各自相互调用)
- 调用了错误的保存、删除重载方法
- Java编程中在子类重载方法中调用父类中该方法时,该方法包含递归时出现的调用错误
- java编译错误:varargs 方法的非 varargs 调用
- 2011/06/13 android使用html做UI的方法---js与java的相互调用
- 在IIS7.5打开网页的时候,提示: HTTP 错误 500.0 - Internal Server Error 调用 LoadLibraryEx 失败,在 ISAPI 筛选器 "C:\Windows\Microsoft.NET\Framework\v4.0.30319\\aspnet_filter.dll" 上。解决方法
- Swift类与OC类方法相互调用的
- php调用存储过程返回结果集,解决can't return a result set in the given context错误的方法
- JVM 方法调用的实现(重载/覆盖)
- iBatis多次调用同一查询语句查询时报“列名无效”无列名的错误原因及解决方法
- iframe 父页面与子页面之间的方法的相互调用
- SQL Server中调用C#类中的方法实例(使用.NET程序集)
- C#中调用DLL时未能加载文件或程序集错误的处理方法(详解)
- iframe 父页面与子页面之间的方法的相互调用
- iOS js oc相互调用(JavaScriptCore)---js调用iOS --js里面通过对象调用方法
- 使用Geoprocessor导出ArcSde中的数据,对COM 组件的调用返回了错误 HRESULT E_FAIL 的解决方法
- client和server相互调用的方法
- Code Fragmen-重载的方法,参数少的去调用参数多的。
- 微信公众号支付之坑:调用支付jsapi缺少参数 timeStamp等错误解决方法