If I have a class like this:
class A {
public string fe = "A";
}
And a class that inherits from it like so:
class B : A {
public string fe = "B";
}
Visual C# will tell me that B.fe hides A.fe so I should use the new keyword. So I change class B to look like:
class B : A {
public new string fe = "B";
}
And then I have a function that takes an A (but, by virtue of inheritance, will also take a B) like this:
class D {
public static void blah(A anAObject) {
Console.Writeline(A.fe);
}
}
Even when I pass it an instance of a B object, which it will take without question, it will print "A"! Why is this, and how can I make it work how I want without setting the variable in the constructor?
That's the difference between override
and new
. new
defines a member which happens to have the same name as a member in the base class. It doesn't override that member. So if you have a method that expects an A
instance, it will take the value of A.fe
and not the member in the derived class with the same name.
Use a property with override
instead:
class A {
public virtual string fe { get { return "A"; } }
}
class B : A {
public override string fe { get { return "B"; } }
}
If you want your fe
member to be overridable by derived classes without having to use the new
keyword (which is why you're seeing the behavior you're seeing), just declare it virtual
in the base class. Then your code would look like this:
public class A
{
public virtual string fe
{
get { return "A"; }
}
}
public class B
{
public override string fe
{
get { return "B"; }
}
}
Notice that this required making fe
a property , since member fields cannot be declared virtual
.
The explanation for why you're not getting the behavior you want is that the new
keyword only overrides an inherited member in the event that a variable is declared as the derived class at compile time. If it's declared as the base class at compile time (as anAObject
is in your blah
method), it goes with the base class version (this is what differentiates new
from override
).
Now, you also could modify your blah
method to cast its input to a B
, thereby accessing your new
fe
:
public static void blah(A anAObject) {
var aBObject = anAObject as B;
if (aBObject != null)
Console.WriteLine(aBObject.fe); // would print "B"
else
Console.WriteLine(anAObject.fe); // would print "A"
}
But I would not recommend this.
class A {
public virtual string fe { get { return "A"; } set {} }
}
class B {
public override string fe { get { return "B"; } set {} }
}
is what you need...
AFAIK in the D.blah()
the object is getting cast of type A
& since the base value is not marked with the virtual
keyword, it would behave as A
& not as B
even if the type is B
...
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.