views:

268

answers:

7

In the following example I am able to create a virtual method Show() in the inherited class and then override it in the inheriting class.

I want to do the same thing with the protected class variable prefix but I get the error:

The modifier 'virtual' is not valid for this item

But since I can't define this variable as virtual/override in my classes, I get the compiler warning:

TestOverride234355.SecondaryTransaction.prefix' hides inherited member 'TestOverride234355.Transaction.prefix'. Use the new keyword if hiding was intended.

Luckily when I add the new keyword everything works fine, which is ok since I get the same functionality, but this raises two questions:

  1. Why I can use virtual/override for methods but not for protected class variables?

  2. What is the difference actually between the virtual/override approach and the hide-it-with-new approach since at least in this example they offer the same functionality?

Code:

using System;

namespace TestOverride234355
{
    public class Program
    {
        static void Main(string[] args)
        {
            Transaction st1 = new Transaction { Name = "name1", State = "state1" };
            SecondaryTransaction st2 = 
                new SecondaryTransaction { Name = "name1", State = "state1" };

            Console.WriteLine(st1.Show());
            Console.WriteLine(st2.Show());

            Console.ReadLine();
        }
    }

    public class Transaction
    {
        public string Name { get; set; }
        public string State { get; set; }

        protected string prefix = "Primary";

        public virtual string Show()
        {
            return String.Format("{0}: {1}, {2}", prefix, Name, State);
        }
    }

    public class SecondaryTransaction : Transaction
    {
        protected new string prefix = "Secondary";

        public override string Show()
        {
            return String.Format("{0}: {1}, {2}", prefix, Name, State);
        }
    }
}
A: 

Why do you want to override a protected variable, surely all you want to do is set it to something else in the overriding class (possibly in the constructor)?

Paddy
This is quite common: Just as I inherit a class and then override certain methods with custom functionality, I want to also inherit a class and override certain variables with certain values. Making each of these little variables full getter methods seems overkill if all they return is a value, and if I have 20 of these, I want them all in a block at the top of the class so I can simply override the ones I need for a certain inheriting class, not have to work through 20 getter methods which extend a couple screens.
Edward Tanguay
If this is the case, then I'm wondering if your design might not need looked at in total - and having seen some of the other comments you have made here, I think that might be the case.
Paddy
what I got out of this is to not hide class variables with new but to use C# properties which can be properly set as virtual and override, makes sense
Edward Tanguay
A: 

You can't because there is no use. What would you accomplish by overriding a field?

Bart van Heukelom
+3  A: 

Rather create a property for the prefix member - this way you can set the property to virtual/abstract

Fields are used to store state for an object, they help the object encapsulate data and hide implementation concerns from others. By being able to override a field we are leaking the implementation concerns of the class to client code (including subtypes). Due to this most languages have taken the decision that one cannot define instance variables that can be overridden (although they can be public/protected... so you can access them).

You also cannot put instance variables in an interface

saret
do you mean make it a Getter (regular method), such as protected string GetPrefix() { return "Secondary"; }, yes this is probably what I am going to do, which has the same functionality but just more code, just wondering what advantage it has over the above hide-with-new example.
Edward Tanguay
Yeah, but you could always have the parent class take the prefix in a constructor (passed in by subtype) and just have one getter for it on the base class - (Edited answer to cover some of the question)
saret
ok this makes me wonder why the hide-with-new option is possible in the first place, I feel that the fact that it worked for me in this situation lured me into writing bad code (hiding internal inherited class variables) as you describe, is this just a bad use of hide-with-new or is hide-with-new to be avoided altogether?
Edward Tanguay
@Edward: In C# I would recommend that you use Properties instead of regular GetX methods.
Svish
The hide with new option is there so that subtypes can use that variable name again (even if it's public on base class) and cause any reference to prefix to refer to the subtypes own prefix member as apposed to the one exposed from the baseclass. any more derived subtype of the original subtype who defined "new prefix" will refer to the new defined field when using prefix field as apposed to the root baseclasses prefix field
saret
@Svish, yes I see what you mean, I put a protected virtual List<string> BlockMarkers { get; } in my base class and in visual studio when I override it in my inheriting class, it pops open a get section where I can define my property, makes sense.
Edward Tanguay
+3  A: 

Overriding a field does not really make sense. It's part of the state of the base class, and if an inheriting class wishes to change it, it should be changable in the inheriting class by giving it an appropriate visibility.

One thing you could do in your case is to set prefix in the constructor for the inheriting class:

// Base class field declaration and constructor
protected string prefix;

public Transaction()
{
  prefix = "Primary";
}

// Child class constructor
public SecondaryTransaction()
{
  prefix = "Secondary";
}

You can also make a property instead of a field, and make the property virtual. This will enable you to change the behavior of the getter and setter for the property in the inheriting class:

// Base class
public virtual string Prefix { get { /* ... */ } set { /* ... */ } }

// Child class
public override string Prefix { get { /* ... */ } set { /* ... */ } }

EDIT: As for your question of using a variable in a base constructor before an inheriting class has set it, one way to solve this is to define an initialization method in the base class, override it in the inheriting class, and call it from the base constructor before accessing any fields:

// Base class
public class Base
{
  protected string prefix;

  public Base()
  {
    Initialize();
    Console.WriteLine(prefix);
  }  

  protected virtual void Initialize()
  {
    prefix = "Primary";
  }
}

// Inheriting class
public class Child : Base
{
  public override void Initialize()
  {
    prefix = "Secondary";
  }
}

EDIT 2: You also asked what the difference between virtual/override and name hiding (the new keyword on methods) is, if it should be avoided, and if it can be useful.

Name hiding is a feature that breaks inheritance in the case of hiding virtual methods. I.e., if you hide the Initialize() method in the child class, the base class will not see it, and not call it. Also, if the Initialize() method was public, external code that was calling Initialize() on a reference of the base type would be calling Initialize() on the base type.

Name hiding is useful when a method is non-virtual in a base class, and a child wants to provide a different implementation of its own. Note, however, that this is NOT the same as virtual/override. References of the base type will call the base type implementation, and references of the child type will call the child type implementation.

Håvard S
right, but in my actual code I am calling the base constructor of the inherited class from my inheriting class's constructor ( e.g. public SecondaryTransaction() : base() ) and the base constructor uses this variable which is at that point not set.
Edward Tanguay
That's a different question than the one you presented here. Please ask the question you want answered.
Håvard S
@Edward, in that case how about having an abstract (and by abstract, I meant virtual) method "Initialise" that you call in your base class ctor, prior to doing *anything*, implement it in your child class and set the value there? I'll add an example of that to my answer
Rob
@HåvardS yes I realize now that that point changes the question a bit, i.e. it is the reason why I need to override the class variable in the first place
Edward Tanguay
@Edward See updated answer.
Håvard S
@Edward Also answered your question on name hiding vs override, and provided a use case.
Håvard S
@HåvardS your last paragraph about hide-with-new makes sense, i.e. why it is not the same as virtual/override (base class will call its own), thanks, interesting.
Edward Tanguay
A: 

Overriding a field is a nonsense. Marking field as protected you automatically may access them in derived classes. You may override functions, properties, because it uses functions internally.

necrostaz
why is hiding a field with new even possible in C# if it is such bad practice?
Edward Tanguay
ok I understand now that you would use hide-with-new in order to give new functionality to an inherited method *that is not virtual*, yet it lacks the advantage of overriding since the inheriting class will still call its own method.
Edward Tanguay
+1  A: 

In your example, if you didn't override "Show" in the SecondaryTransaction class, then calling Show on an instance of SecondaryTransaction would actually be calling the method in the base class (Transaction), which would therefore use "Show" in the base class, resulting in output of:

Primary: name1, state1 
Primary: name1, state1

So, depending on what method you were calling (i.e. one on the base class or the child class), the code would have a different value for "prefix" which would be a maintainability nightmare. I suspect what you probably want to/should do, is expose a property on Transaction that wraps "prefix".

You can't override a field because it's an implementation detail of the base class. You can change the value of a protected field, but by overriding it you'd essentially be saying I want to replace the field, not the value.

What I would do (if I absolutely didn't want to/couldn't use properties) :

public class Transaction
{
    public string Name { get; set; }
    public string State { get; set; }
    protected string prefix = "Primary";
    public virtual string Show()
    {
        return String.Format("{0}: {1}, {2}", prefix, Name, State);
    }
}
public class SecondaryTransaction : Transaction
{ 
    public SecondaryTransaction()
    {
        prefix = "Secondary";
    }
    public override string Show()
    {
        return String.Format("{0}: {1}, {2}", prefix, Name, State);
    }
}

Edit: (As per my comment on another answer)

If you're calling down into your base class's ctor and need the value set, then you'll probably have to modify Transaction, possibly like this:

public class Transaction
{
    public string Name { get; set; }
    public string State { get; set; }
    protected string prefix = "Primary";
    // Declared as virtual ratther than abstract to avoid having to implement "TransactionBase"
    protected virtual void Initialise()
    { }
    public Transaction()
    {
        Initialise();
    }
    public virtual string Show()
    {
        return String.Format("{0}: {1}, {2}", prefix, Name, State);
    }
}
public class SecondaryTransaction : Transaction
{ 
    protected override void Initialise()
    {
        prefix = "Secondary";
    }
    public override string Show()
    {
        return String.Format("{0}: {1}, {2}", prefix, Name, State);
    }
}
Rob
ok, this is educational, I know now that in the above case the best thing to do is to create a property getter for each variable which I want to either override or leave as-is in my inheriting classes. I THOUGHT I had finally found a use for the hide-with-new feature in C#, yet if this use of it is such bad practice, then I don't understand when I would ever use it in good practice.
Edward Tanguay
@Edward, I've never found a use for it. That doesn't mean there isn't one though :)
Rob
A: 

A static or non-virtual method or property is just a memory address (to simplify things). A virtual method or property is identified by an entry in a table. This table is dependent on the class defining the method or property. When you override a virtual member in a derived class, you actually change the entry in the table for the derived class to point to the overriding method. At run-time, access to such a member goes though the table, always. So the entry can be overridden by any derived class.

There is no such mechanism for fields, as they're meant to be accessed quickly.

Using 'new' on a member means that you do not want to override the entry in the table, but that you want a new member (with the same name as an existing virtual one, a bad practice if you ask me).

If you access a virtual member through a pointer to the base class, you'll never access the member defined as 'new' in the derived class, which is the difference mentioned in the second part of your question.

Timores