首页 > 开发 > 综合 > 正文

C#类中虚方法相互调用的潜在重载错误

2024-07-21 02:27:07
字体:
来源:转载
供稿:网友

   当我们编写基类虚方法时,需要注意一个问题,就是基类中虚方法的相互调用,有可能引起派生类重载时的潜在错误隐患。当然这个错误并不是c#语言设计的缺陷,而是一个不可避免的实现而已。当然如果我们是要编写通用的组建基类,就需要注意一下了。

    或许我们刚开始做oop的时候,对于有没有方法有没有virtual根本不在乎,很多是时候我们都重写了(rewrite)了基类方法。当然在需要确定重载(override)的时候,virtual关键字限定基类方法是不可少的。那么是不时我们就可以把基类的方法都弄成virtual修饰的呢?这样虽然在大多时候没有问题,而其如果是自己重载自己的基类出问题的可能性也不大,可是如果是别人来继承基类,那么问题可能就来了。

    当我们重载不确切的基类是,最好的习惯是调用以下base的同名方法,这个在控件开发时用的更加普遍。可是这个时候,如果基类之间存在虚方法调用了别的被重载的虚方法,潜在错误就出来了。看下面示例(由xingd提供,我修改): using system;

public class base
{
    public virtual void foo()
    {
        console.writeline("base::foo");
        this.bar();
    }
    public virtual void bar()
    {
        console.writeline("base::bar");
    }
};

public class derived : base
{
    private object obj;
    public override void foo()
    {
        console.writeline("derived::foo");
        base.foo();
        obj = new object();
        this.bar();
    }
    public override void bar()
    {
        console.writeline(obj.tostring());
        console.writeline("derived::bar");
    }
};

public class test
{
    public static void main()
    {
        derived b = new derived();
        b.foo();
    }
};
    编译没有错误,当然了,又不是在里讲c#语法。运行结果为:    e:/working/doing>test
   derived::foo
   base::foo

   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来控制方法是否需要重载,所以这类问题完全是由代码的设计缺陷所引起的,而且如果由一个人来写一般是不会设计出这样的代码的,可是如果基类和派生类由不同的人来写,出这样的错误的机会可能就会更大一些。

商业源码热门下载www.html.org.cn

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表