50

I'm trying to refresh my memory but can't find answers with Google.

public class BaseClass
{
    public virtual void DoSomething()
    {
        Trace.Write("base class");
    }
}

public class DerivedClass : BaseClass
{
    public override void DoSomething()
    {
        Trace.Write("derived class");
    }
}

If I create an instance of derived class, how do I convert it to it's base class so that when DoSomething() is called, it uses the base class's method only?

A dynamic cast still calls the derived class's overridden method:

DerivedClass dc = new DerivedClass();

dc.DoSomething();

(dc as BaseClass).DoSomething();

Output: "derived class"

oberfreak
  • 1,799
  • 13
  • 20
Levitikon
  • 7,749
  • 9
  • 56
  • 74
  • 1
    Kind of defeats the purpose of inheritance, typically in your override though you would manually invoke `base.DoSomething()` but barring that you may be able to do something with reflection. – Paul Tyng Nov 30 '11 at 16:37
  • Ouch, I thought it would be something simple I overlooked. Thanks – Levitikon Nov 30 '11 at 16:38
  • possible duplicate of [How to invoke (non virtually) the original implementation of a virtual method?](http://stackoverflow.com/questions/3378010/how-to-invoke-non-virtually-the-original-implementation-of-a-virtual-method) – Ani Nov 30 '11 at 16:39

6 Answers6

58

Although this sounds irrational but it works

 DerivedClass B = new DerivedClass();

BaseClass bc = JsonConvert.DeserializeObject<BaseClass>(JsonConvert.SerializeObject(B));
Sugar Bowl
  • 1,722
  • 1
  • 19
  • 24
  • 2
    Deep copy is one of the acceptable solutions, but it comes at a performance cost. – Levitikon Dec 13 '13 at 11:52
  • 2
    Where does this put the extra properties that may be in the derived class when serializing into the base class? Eg. StudentDerived class introduced Height of student while inheriting from StudentBase. – Vaibhav May 16 '16 at 09:12
  • 2
    @Vaibhav It just ignores all the extra properties :) – Kasper Vesth May 29 '16 at 16:52
  • 2
    Ok, but this kind of an anti-pattern should only be used -- though not justified -- when extending an exception or circumventing a situation. This kind of an OOP violation definitely calls for a design re-consideration. – Vaibhav May 30 '16 at 09:34
  • 5
    All academic "anti-pattern" arguments aside, sometimes the easiest solution is the correct one. This solution works very nicely! Consider extending an entity model then trying to save the base entity after it is handed back from the client. This is a problem. Do you want to write tons of code extracting the base model, or just use this? – iGanja Jun 30 '16 at 19:06
  • I agree it is kind of a round about way to do this, but in certain situations it may make sense. I had the exact situation iGanja mentions where the EF entity was extended, then needed to be sent back through code which updates the entity via EF. – Shiloh Jan 17 '17 at 05:15
  • This is a workaround at best. Not "easy" and definitely not a "solution". – The incredible Jan Jun 29 '23 at 11:15
50

You can't - that's entirely deliberate, as that's what polymorphism is all about. Suppose you have a derived class which enforces certain preconditions on the arguments you pass to an overridden method, in order to maintain integrity... you don't want to be able to bypass that validation and corrupt its internal integrity.

Within the class itself you can non-virtually call base.AnyMethod() (whether that's the method you're overriding or not) but that's okay because that's the class itself deciding to potentially allow its integrity to be violated - presumably it knows what it's doing.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Thanks Jon. I want to make it clear, I very much enjoy and rely on the properties and methods of derived classes to be in effect even when the class is casted to it's base class. It would just be very nice also to strip away derived classes under certain special conditions. It looks like reflection or some sort of deep copy is the way to go. – Levitikon Nov 30 '11 at 16:47
  • 1
    Are we sure this is the correct answer? Looks like you can call the base method if the derived class used the new keyword rather than overriding a virtual member of the base class. –  Oct 28 '14 at 19:16
  • 1
    @winnicki: At that point it's not the same situation as in the question. You could call the base class method if you didn't have the derived class method at all, or if it had a different name, or a different number of parameters etc... – Jon Skeet Oct 28 '14 at 20:56
  • @JonSkeet After reading the question carefully again I see what you mean. –  Oct 30 '14 at 01:47
  • Using new seems to be exactly what he is looking for. Remove virtual, pop in new instead of override and his code works exactly how he wants it to. How is it not the same situation as in the question? – Jason Kelley Oct 25 '18 at 04:15
  • 1
    @Loophole: Yup, `new` instead of `override` would indeed work, if the OP can do that. It's not entirely clear from the question whether it's about "what can I do with classes like this that I can't change" or "how can I change the classes themselves to behave in a different way". – Jon Skeet Oct 25 '18 at 12:40
14

You absolutely CAN (call the base method), just read up on Polymorphism:

https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/polymorphism

Example:

public class BaseClass
{
    public void DoWork() { }
    public int WorkField;
    public int WorkProperty
    {
        get { return 0; }
    }
}

public class DerivedClass : BaseClass
{
    public new void DoWork() { }
    public new int WorkField;
    public new int WorkProperty
    {
        get { return 0; }
    }
}

And how to call it:

DerivedClass B = new DerivedClass();
B.DoWork();  // This calls the new method.

BaseClass A = (BaseClass)B;
A.DoWork();  // This calls the old method.
Papa Burgundy
  • 6,397
  • 6
  • 42
  • 48
4

Try using the new keywor instead of override As far as i know this should enable that desired behavior. I'm not realy sure about that so please don't blame me if i'm wrong!

public class BaseClass
{
    public virtual void DoSomething()
    {
        Trace.Write("base class");
    }
}

public class DerivedClass : BaseClass
{
    public new void DoSomething()
    {
        Trace.Write("derived class");
    }
}
oberfreak
  • 1,799
  • 13
  • 20
2

The solutions with new instead of override break the polymorphism. Recently I came to the same problem and implemented it the following way. My solution has the following advantages:

  • virtual and override stays in place;
  • name BaseClass is not used directly in the type cast, so if I introduce an intermediate MiddleClass in the hierarchy between BaseClass and DerivedClass, which also implements DoSomething(); then the MiddleClass's implementation won't be skipped.

This is the implementation:

public class BaseClass
{
    public virtual void DoSomething()
    {
        Trace.Write("base class");
    }
}

public class DerivedClass : BaseClass
{
    public override void DoSomething()
    {
        Trace.Write("derived class");
    }

    public void BaseDoSomething()
    {
        base.DoSomething();
    }
}

The usage is:

    DerivedClass dc = new DerivedClass();

    dc.DoSomething();

    dc.BaseDoSomething();
Andrej Adamenko
  • 1,650
  • 15
  • 31
1

For VB.net, I've used the following code to do the conversion (shown with Lists of Objects):

        Dim tempPartialList As New List(Of clsBaseData)

        For Each iterClsDerivedData As clsDerivedData In ListOfDerivedDataObjects
            tempPartialList.Add(CType(iterClsDerivedData, clsBaseData))
        Next

Where clsBaseData is the Base Class from which clsDerivedData is made by Inheriting clsBaseData.

ListOfDerivedDataObjects is a List(Of clsDerivedData).

I have found this useful where I have Lists of several Derived Classes and I would like to operate on a property of the Base Class for all the objects in the Lists of Derived Classes. The tempPartialList is, for me, a temporary List meant to facilitate changing this property.

DSchmidt
  • 11
  • 3