Alex Rivera | Logout

Why can't I use virtual/override on class variables as I can on methods?

Asked 2010-03-04T10:16:26.870
16

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";

        publi
Edit
Report

1 Answer

1

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 virtua
answered 2010-03-04T10:28:00.357

Your Answer