4

How exactly does this work?

If I have this base class

public class BaseClass
{
    public int Value1 { get; set; }
    public int Value2 { get; set; }

    public BaseClass SimpleClone()
    {
        BaseClass result = new BaseClass();
        result.Value1 = this.Value1;
        result.Value2 = this.Value2;
        return result;
    }
}

And this child class

public class DerivedClass : BaseClass
{
    public bool Value3 { get; set; }

    public DerivedClass()
    {
        Value3 = true;
    }
}

How can I downcast BaseCast.SimpleClone() into anotherObj? What would happen to Value3? While knowing what happens is good, I am also interested in why it works this way.

Kyle Baran
  • 1,793
  • 2
  • 15
  • 30
  • You mean "downcast [...] into `DerivedClass`"? If not, please show `anotherObj`, or even better just show the code that does the downcast. –  May 11 '14 at 09:51

4 Answers4

5

If I understand correctly your question is What happens when you do the following

DerivedClass derived = (DerivedClass)baseObj.SimpleClone();

Did you try that? Simply it will result in InvalidCastException since BaseClass is not DerivedClass.

I have answered a similar question here, That should clear things up.

Community
  • 1
  • 1
Sriram Sakthivel
  • 72,067
  • 7
  • 111
  • 189
  • So I am only able to downcast a `BaseClass` object into a `DerivedClass` if I make a reference to a `BaseClass` that is supplied an instance of `DerivedClass`? That seems very specific to work with in most cases. – Kyle Baran May 11 '14 at 09:58
  • Exactly. To get the cast work the instance needs to be `DerivedClass` or one of its sub class(MoreDerivedClass). Or there exist an [explicit conversion](http://msdn.microsoft.com/en-us/library/85w54y0a.aspx) – Sriram Sakthivel May 11 '14 at 10:01
2

The answer to your downcast is no, it can't be done as per SriRam's answer. Although rather messy, you could achieve your cloning by using polymorphicism. You will probably need to split out the concerns of creation and assignment when doing so:

public class BaseClass
{
    public int Value1 { get; set; }
    public int Value2 { get; set; }

    protected virtual BasedClass Create()
    {
       return new BaseClass();
    }

    public virtual BaseClass SimpleClone()
    {
        var clone = Create(); // The appropriate create will be called
        clone.Value1 = this.Value1;
        clone.Value2 = this.Value2;
        return clone;
    }
}

public class DerivedClass : BaseClass
{
    public bool Value3 { get; set; }

    public DerivedClass()
    {
        Value3 = true;
    }

    protected override BasedClass Create()
    {
       return new DerivedClass();
    }

    public override BaseClass SimpleClone()
    {
       var result = base.SimpleClone();
       (result as DerivedClass).Value3 = this.Value3;
    }
}
StuartLC
  • 104,537
  • 17
  • 209
  • 285
  • Hey, Stuart, I don't think the question was *how to solve my problem*. It was related to theory I suppose. OP wanted to know *what would happen and why*, rather than *how could I correct my code* – Amit Joki May 11 '14 at 10:03
  • Yeah, I was speculating on what the OP was trying to do. Possibly OP comes from a background where unsafe type casting is allowed, e.g. C. – StuartLC May 11 '14 at 10:05
2

The question as it stands does not make sense. There is no possibility for downcasting, because your clone method already returns the base class. What I think you do (should) want here is override the clone method in your subclass:

public class DerivedClass : BaseClass
{
    //... Other stuff
    public BaseClass SimpleClone()
    {
        var result = new DerivedClass 
                         {
                             Value1 = this.Value1,
                             Value2 = this.Value2,
                             Value3 = this.Value3,
                         }
        return result;
    }

Now, if you have an object of type DerivedClass and call clone on it, the compiler does not know that the returned object is of type DerivedClass, because of the method signature. But you do, so in that case you can cast the object. All it does is tell the compiler: 'I know better, you think this is a BaseClass but it actually is a DerivedClass'. It has no runtime impact because you don't change the type of the object, you only provide the compiler with extra information.

Vincent van der Weele
  • 12,927
  • 1
  • 33
  • 61
  • Admittedly my question was sparked by a random thought in the wee hours of the morning, so I unfortunately didn't give it much thought before asking it here. However, this answer is probably the closest thing to what I was imagining. Thanks! – Kyle Baran May 11 '14 at 23:37
1

It doesn't work that way. Casting is way of telling the compiler to treat the object as if it was the object of casting class, and you are aware of information loss.

Just because a derived class is derived from base class doesn't necessarily mean that both are same.

So, you will get InvalidCastException.

Amit Joki
  • 58,320
  • 7
  • 77
  • 95