1

I'm sure this is a duplicate but I can't find an answer. I'm new to C# and having trouble understanding why this is happening:

I have one class that inherits from another. I want the subclass to override a public field on the superclass, in this case the public field a. But it doesn't seem to work:

class Foo
{
   public string a = "x";

   public string A()
   {
      return a;
   }
}

class Bar : Foo
{
   public string a = "y";
}

...

new Foo().A() // Returns "x"
new Bar().A() // Returns "x" also...why?

I would expect the last line to return "y" but instead it returns "x", ignoring the fact that I've overridden the value of the a field. Why isn't it working? And what is the standard way of getting the behavior I want?

I'm entering this code into the csharp REPL, if that matters.

GladstoneKeep
  • 3,832
  • 2
  • 26
  • 38
  • Methods are overridden, not fields. You can use virtual methods for this behavior. – Zdeslav Vojkovic Nov 17 '20 at 23:35
  • https://stackoverflow.com/questions/326223/overriding-fields-or-properties-in-subclasses – Jonesopolis Nov 17 '20 at 23:38
  • 2
    Note the compiler warning about this: `'Bar.a' hides inherited member 'Foo.a'. Use the new keyword if hiding was intended`. This hints that something is not good with this code and in fact, you aren't overriding the field as you think. – Alejandro Nov 17 '20 at 23:39

2 Answers2

4

Your code is shadowing the field, not overriding it.

It's the equivalent of this code:

class Bar : Foo
{
    public new string a = "y";
}

Your compiler should have given you a warning on this code.

Now, since you're shadowing it means that in a call to A the field in Foo is used and it's like the field in Bar doesn't exist.

You can't override a field, but if you change the field to a property then you can do this:

class Foo
{
    public virtual string a { get; set; } = "x";

    public string A()
    {
        return a;
    }
}

class Bar : Foo
{
    public override string a { get; set; } = "y";
}

Now your code would behave as you first thought it would:

void Main()
{
    Console.WriteLine(new Foo().A()); //x
    Console.WriteLine(new Bar().A()); //y
}
Enigmativity
  • 113,464
  • 11
  • 89
  • 172
0

You have to mark property a with virtual and override it in the subclass.

In Foo: public virtual string a { get; set; } = "x";

In Bar: public override string a { get; set; } = "y";

Ergis
  • 1,105
  • 1
  • 7
  • 18
  • Technically there is also the [`new` keyword](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/new-modifier), which might be more in line with what the OP was expecting. – Sean Skelly Nov 17 '20 at 23:36