简体   繁体   中英

Property returns string from base class while member returns string from inherited class?

Here is the program:

public class Program
{
    static void Main()
    {
        MyInheritedClass InheritInstance = new MyInheritedClass();
        Console.WriteLine(InheritInstance.name); // the name field
    }
}

public class MyClass
{
    public string name= "I am the Base"; // the name field
    public string Name   // the Name property
    {
        get
        {
            return this.name;
        }
    }
}

public class MyInheritedClass : MyClass
{
    new public string name= "I inherit Base";
}

This works as expected. the output is: "I inherit Base"

Now if I change Console.WriteLine(InheritInstance.name); // the name field Console.WriteLine(InheritInstance.name); // the name field to Console.WriteLine(InheritInstance.Name); // the name property Console.WriteLine(InheritInstance.Name); // the name property , it magically outputs: "I am Base"

I am baffled as to WHY this happens? I called the Name property of MyInheritedClass , how did the Name property of MyClass get called? Or maybe the Name property of MyClass is called and it somehow magically accesses the name field of MyClass ?

Now if I change Console.WriteLine(InheritInstance.name); // the name field to Console.WriteLine(InheritInstance.Name); // the name property, it magically outputs: "I am Base"

This happens because MyClass is unaware of the new operator in your derived class. As far as it knows, it only has one string field called Name , which is declared in the base class. When the property has the retrieve it via the getter, it goes to the name declared there.

As the docs say:

When used as a declaration modifier, the new keyword explicitly hides a member that is inherited from a base class. When you hide an inherited member, the derived version of the member replaces the base class version

If you want to override that behavior, you can declare name as virtual :

public class MyClass
{
    public string name = "I am the Base";
    public virtual string Name { get { return this.name; } }
}

public class MyInheritedClass : MyClass
{
    public new string name = "I inherit Base";
    public override string Name { get { return this.name } };
}

Note this looks and feels redundant. You can avoid that by declaring a single virtual property:

public class MyClass
{
    public virtual string Name { get { return "I am base" } }
}

public class MyInheritedClass : MyClass
{
    public override string Name { get { return "I am derived" } };
}

It calls your base class property because the Name property is defined only in the base class. This is the default and simplest behavior of inheritance. You can access properties from the base class.

When you need control over a property from the Base class you can use the override or new constructs to define your desired behavior for the property in the Child class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM