C# 为什么派生类中重写的自动实现属性的值与C中的虚拟基类属性的值不同

C# 为什么派生类中重写的自动实现属性的值与C中的虚拟基类属性的值不同,c#,inheritance,properties,overriding,C#,Inheritance,Properties,Overriding,我有一个“base”,它有一个名为“id”的虚拟int自动实现属性 class bbase { public virtual int id { get; set; } } 当我从这个类继承到一个“派生”类时,我得到: class Derived : bbase { public override int id { get { return base.id; } set

我有一个“base”,它有一个名为“id”的虚拟int自动实现属性

class bbase
{
    public virtual int id { get; set; }

}
当我从这个类继承到一个“派生”类时,我得到:

class Derived : bbase
{
    public override int id
    {
        get
        {
            return base.id;
        }
        set
        {
            base.id = value;
        }
    }
}
初始化基类和派生类并将值指定给基类属性后,如下所示:

bbase b2 = new bbase();
Derived d2 = new Derived();
b2.id = 6;
bbase b2 = new bbase();
bbase d2 = new bbase();
b2.id = 6;
Console.WriteLine(d2.id);
当我尝试从派生类输出值时,它输出“0”:

Console.WriteLine(d2.id);
我的困惑是,当我用虚拟方法尝试相同的方法时,效果很好。带有base.method的派生类方法运行良好。它返回基方法中的任何内容,但为什么不使用自动实现的属性呢

class bbase 
{
    public virtual void execute() { Console.WriteLine("base.execute2"); }
}

class Derived : bbase
{
     public override void execute()
     {
         base.execute();
     }
}
b2和d2是不同的对象。你可以说,因为你每次都做了一次新的


如果将属性设置为静态,则会看到预期的结果。

两者都是两个独立的对象。所以你看到的是预期的结果

如果您重新编写代码,使变量b2和d2都指向派生类对象,则可以进行模拟,如下所示:

Derived d2 = new Derived();
bbase b2 = d2;
b2.id = 6;
Derived d2 = new Derived();
bbase b2 = d2;
b2.id = 6;
Console.WriteLine("d2:"+d2.id);
Console.WriteLine("b2: "+b2.id);
现在如果你这样做了:

Console.WriteLine(d2.id); // prints 6
您将看到上面设置的相同值

理想情况下,我认为您不应该像上述情况那样在属性getter和setter中那样调用base,因为您没有对base的值做任何特殊的处理,因此,只需在派生中使用默认的get和set,如:

class Derived : bbase
{ 
    public override int id
    {
        get;
        set;
    }
}
现在,如果你写下以下内容:

Derived d2 = new Derived();
bbase b2 = d2;
b2.id = 6;
Derived d2 = new Derived();
bbase b2 = d2;
b2.id = 6;
Console.WriteLine("d2:"+d2.id);
Console.WriteLine("b2: "+b2.id);
它将输出:

d2:6

b2:6

请参阅以了解它。

实际上b2和d2是不同的对象。 因此,如果设置b2.id=6;然后d2保持为0,只要您还设置了d2.id=6


在您的虚拟方法示例中,您通过重写它返回base method=>base.execute;,这就是为什么即使实例化d2类,也会得到基本方法输出。

如果代码如下所示:

bbase b2 = new bbase();
Derived d2 = new Derived();
b2.id = 6;
bbase b2 = new bbase();
bbase d2 = new bbase();
b2.id = 6;
Console.WriteLine(d2.id);
你会期望结果不是0吗?这是相同的区别

只有将派生类指定给基类的引用时,重写、隐藏和其他多形才起作用


这种赋值在任何OOP语言中都经常发生。这是使用OOP的1/2到3/4点。

我认为您在这里遗漏了一些基础知识

bbase类将实例级属性id定义为虚拟。这意味着它可以被覆盖:

class bbase
{
    public virtual int id { get; set; }
}
派生类重写实例级属性id:

这意味着派生的任何实例都以这种重写方式处理id属性

实例化对象时:

bbase b2 = new bbase();
Derived d2 = new Derived();

您正在创建每个类的实例。这些实例的属性有自己的值。继承不相关,因为它们是两个独立的实例。您对d2所做的任何操作都不会反映在b2中,因为它们是不同的

b2没有以任何方式连接到d2实例。你可以投,b2=bbased2;请注意,它是有效的,但您正在创建两个完全不同的对象,它们包含的值彼此没有关联;现在都是零B2和d2不是同一个实例吗?为什么您希望在其中设置一个值会对另一个产生影响?当然,在那个次强制转换之后,两者都是零——您仍然并没有设置d2。若有,重写虚拟成员的理想效果是替换实现。因此,如果您有派生实例的List和store,那么在调用虚拟成员时将调用后一种类型的实现。继承和重写都与两个不同的实例无关。方法是类的行为,它们没有值。但是财产有价值。因此,基类和派生类的两个不同对象可能具有相同的行为,但它们的属性可能不具有相同的值。但这些方法也源自不同的对象,但它们产生相同的结果。为什么属性不同?或者我不明白?@M.Asif方法存在于基类和派生类中,就像属性一样。不同之处在于,您正在为属性指定一个值,并希望将其传递给另一个对象。我们不是从派生类调用基类方法实现吗??类bbase{public virtual void execute{Console.WriteLinebase.execute2;}}}派生类:bbase{public override void execute{base.execute;}}}}@M.Asif Yes,并且该属性也在调用基实现。差异就是价值。方法调用中没有涉及实例值。这是可行的,但我仍然有点困惑,方法和属性显然都是以相同的方式实现的,但是属性需要强制转换,但方法还没有。方法和属性都来自不同的对象。为什么会这样?@M.Asif当您从子类类型变量强制转换为父类变量时,您不需要强制转换,但在其他情况下需要paren
t type变量到child您在示例中使用d2两次打印感谢@Antry的更正,当这两个类都有不同的对象和虚拟方法时,我正试图学习这一点,并说明为什么派生类方法能够输出基类方法实现,但不能property@M.Asif属性有值,方法是动作。属性的值随着实例的变化而变化。属性携带值和方法只是类的行为,这似乎是合乎逻辑的