3

Say I have the following code:

class Parent
{

    static string MyField = "ParentField";

    public virtual string DoSomething()
    {
        return MyField;
    }
}

class Child : Parent
{
    static new string MyField = "ChildField";
}

Now I want to be able to do both of the following:

Console.WriteLine(Parent.MyField);
Console.WriteLine(Child.MyField);

These work as expected, but I would also like to do this:

Child c = new Child();
Console.WriteLine(c.DoSomething());

Since DoSomething() is not defined for the Child class, it's the Parent's MyField that gets returned, but what I want is the Child's MyField.

So my question is: Is there any way I can do this?

NOTE: Overriding the method in the Child class is an option, but since I will have lots of Child classes inheriting from the Parent and the method is supposed to do the same in all of them, changing something in this method would bring a lot of trouble.

Francisco Silva
  • 530
  • 1
  • 7
  • 21

9 Answers9

7

If you find yourself requiring a construct not supported by the language, in this case static virtual members, that is a smell, indicating you might have a faulty design.

Instead of showing us a solution, show us the problem you are trying to solve with that solution. My guess is that there is a totally different design that eliminates the need for this oddity.

Put another way: the answers you've received aren't the ones you want because the question you asked is not really the question you should be asking. I can think of no situation where the proposed design offers benefits that another, more conventional design does not.

Bryan Watts
  • 44,911
  • 16
  • 83
  • 88
  • +1 I'd be interested to see a more complete outline of the problem myself. – Chuck Wilbur Mar 10 '10 at 21:32
  • My problem is really complex and I can't get into more detail without getting way too confusing (even for myself). I understand now my design is definitely wrong and I will have to sit and think of a better solution. Thanks to everyone for your answers. – Francisco Silva Mar 11 '10 at 00:18
1

You have to handle this in Child, too:

class Child
{
    static new string MyField = "ChildField";

    public override string DoSomething()
    {
         return MyField;
    }
}

That being said, using a single virtual property would probably be a cleaner design, since you wouldn't need the "new" keyword to hide the Parent's member field.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • I understand I can do this, but I would like also to avoid overriding the method since there are multiple Child classes and the method is supposed to do the same in all of them. Sorry I forgot to mention it in the original post. – Francisco Silva Mar 10 '10 at 20:08
  • @Francisco: Just make a (potentially) protected, virtual (non-static) property that returns a constant, and return that. Then you just have to override the property... – Reed Copsey Mar 10 '10 at 20:09
  • That's much better than overriding the method. The downside is that I have to override/new 2 "things" instead of just 1. And have to access the property in non-static environments and the constant in static environments. Any other ideas? – Francisco Silva Mar 10 '10 at 20:19
1

I don't get why you think you need both "static" and "non-static" environments to call different properties/functions that return the same thing. If you just do this:

class Parent
{
    public virtual string DoSomething()
    {
        return "ParentField";
    }
}

class Child
{
    public override string DoSomething()
    {
         return "ChildField";
    }
}

Then this will work like you want:

Child c = new Child();
Console.WriteLine(c.DoSomething());

And instead of writing this:

Console.WriteLine(Parent.MyField);
Console.WriteLine(Child.MyField);

you just write this:

Console.WriteLine(new Parent().DoSomething());
Console.WriteLine(new Child().DoSomething());

Is there some other constraint on the problem that makes this unacceptable? Is creating new objects of these classes extremely expensive for some reason, for example?

Chuck Wilbur
  • 2,510
  • 3
  • 26
  • 35
0

Use a static property instead of a static variable. Then you can override the property in the child class instead of creating a "new" field.

Jesse Weigert
  • 4,714
  • 5
  • 28
  • 37
0

Yes, override DoSomething:

class Child
{
    static new string MyField = "ChildField";

    public virtual string DoSomething()
    {
        return MyField;
    }

}
BFree
  • 102,548
  • 21
  • 159
  • 201
0

There's no inheritance magic on anything static but you could dó this

protected virtual string { get { return "your value"; } }

and use the property inside your method

Rune FS
  • 21,497
  • 7
  • 62
  • 96
0

In one response you seem to indicate that the static field is constant. If that is the case, then this should work for you.

class Parent
{
    protected virtual string MyField() { return "ParentField"; }

    public virtual string DoSomething()
    {
        return MyField();
    }
}

class Child : Parent
{
    protected override string MyField() { return "ChildField"; }
} 
Jeffrey L Whitledge
  • 58,241
  • 9
  • 71
  • 99
0

The only way is overriding DoSomething method or else it is not possible. The DoSomething in Parent method essentially translates to:

public virtual string DoSomething()
    {
        return Parent.MyField;
    }

When you "new" a property, it only applies to that type - in this case Child class. If the property is accessed via the 'Parent', it will always return the original property.

Vivek
  • 16,360
  • 5
  • 30
  • 37
0

First, let me say that you really should just make MyField virtual and accept that you need to spawn an instance to get it. However, another way of "solving" the problem would be:

class Parent
{
    public static string MyField = "ParentField";
    protected virtual MyLocalField = MyField;

    public virtual string DoSomething()
    {
        return MyLocalField;
    }
}
class Child : Parent
{
    public static new string MyField = "ChildField";
    protected override MyLocalField = MyField;
}
Thomas
  • 63,911
  • 12
  • 95
  • 141