为什么被重写的虚拟属性总是指向基类的属性的 getter 和 setter 方法

本文关键字:属性 getter 基类 setter 方法 重写 虚拟 为什么 | 更新日期: 2023-09-27 18:35:29

一个理论问题。我在类中有一个虚拟属性。另一个扩展该类的类,即使覆盖了虚拟属性,似乎从未真正覆盖基属性的 getter 或 setter 方法。我错过了什么?

class BaseClass
{
    protected string bla;
    public virtual string Bla
    {
        get { return this.bla; }
        set { this.bla = value; }
    }
    protected BaseClass() { } 
    public BaseClass(string _bla)
    {
        this.Bla = _bla;
    }
}
class ChildClass : BaseClass
{
    private string bla2;
    public override string Bla
    {
        get
        {
            return bla2;
        }
        set
        {
            bla2 = value;
        }
    }
    public ChildClass(string _bla2) : base("AAA")
    {
        this.Bla = _bla2;
    }
}
class Program
{
    static void Main(string[] args)
    {
        var c = new ChildClass("Me");
        Console.WriteLine(c.Bla);
        Console.ReadLine();
    }
}

我想,我得到了答案。

为什么被重写的虚拟属性总是指向基类的属性的 getter 和 setter 方法

如果修复代码以便编译,它将按预期工作。但是,请注意我添加的评论!您正在从构造函数调用虚拟方法(属性资源库,但仍然是方法)。这很糟糕。

using System;
namespace Demo
{
    class BaseClass
    {
        protected string bla;
        public virtual string Bla
        {
            get
            {
                return this.bla;
            }
            set
            {
                this.bla = value;
            }
        }
        protected BaseClass()
        {
        }
        public BaseClass(string _bla)
        {
            this.Bla = _bla;
        }
    }
    class ChildClass: BaseClass
    {
        private string bla2;
        public override string Bla
        {
            get
            {
                return bla2;
            }
            set
            {
                bla2 = value;
            }
        }
        public ChildClass(string _bla2)
            : base("AAA")
        {
            // Step into the next line of code in the debugger.
            // You'll see that it goes into the ChildClass.Bla setter.
            // However note that this is making a virtual call in a constructor 
            // - which is very bad if there is a further derived class because
            // it will call a method in that derived class before that derived
            // class has been constructed.
            // You can fix this potential problem by making this entire class
            // sealed or by making the property sealed in this class.
            this.Bla = _bla2; 
        }
    }
    class Program
    {
        private void run()
        {
            var c = new ChildClass("X");
        }
        static void Main(string[] args)
        {
            new Program().run();
        }
    }
}

base("AAA")调用public BaseClass(string _bla) { this.Bla = _bla; },将this.Bla的值(在子类中它指向字段bla2)设置为"AAA",因此在public ChildClass(string _bla2) { this.Bla = _bla2; } this.Blabla2中已经通过基构造函数分配。

我用你的代码做了一个单元测试,它可以工作,添加子类:

    public override string ToString()
    {
        return string.Format("bla = {0},bla2 ={1}", bla,bla2);
    }

设置属性后调用此方法。

你会看到bla=nullbla2="Something"

编辑如评论中所述,我不得不将 setter 的可见性级别更改为公共,删除子类中的构造函数