Adam Beck
Adam Beck

Reputation: 1271

Casting from Base To Derived?

Is it possible to cast an object from a base to a derived one? For instance, let's say I have one base object: Animal. From this I have derived a couple of other classes: Cat, Dog. Now I need an Animal but the type at this moment doesn't really matter. So,

Animal blankCanvas = new Animal();

Along the way I changed my mind and now want to change that Animal to a Dog. However, I don't understand how I would go about doing that. I know the business rules to convert from an Animal to a Dog but I just don't know how to implement that.

Upvotes: 3

Views: 2575

Answers (5)

Strillo
Strillo

Reputation: 2972

You can either use a static method on the derived class like this:

/// <summary>
/// Dog.
/// </summary>
class Dog : Animal
{
    /// <summary>
    /// Initializes a new instance of the <see cref="Dog"/> class.
    /// </summary>
    /// <param name="type">The type.</param>
    public Dog(string type)
        : base(type)
    { }

    /// <summary>
    /// Gets a dog from an animal.
    /// </summary>
    /// <param name="animal">The animal.</param>
    /// <returns></returns>
    public static Dog FromAnimal(Animal animal)
    {
        return new Dog(animal.Type);
    }
}

/// <summary>
/// Animal.
/// </summary>
class Animal
{
    /// <summary>
    /// Gets or sets the type.
    /// </summary>
    /// <value>The type.</value>
    public string Type { get; private set; }

    /// <summary>
    /// Initializes a new instance of the <see cref="Animal"/> class.
    /// </summary>
    /// <param name="type">The type.</param>
    public Animal(string type)
    {
        this.Type = type;
    }
}

Or use a single factory class to manage all the conversions you need.

Upvotes: 2

Henk Holterman
Henk Holterman

Reputation: 273169

Yes, you can cast a base reference to a derived reference.

But you seem to want to convert an instance. That is not casting and it is not directly possible.

Your logic should be such that you know what type you want at the point when you create it.

The following could make sense:

Animal blankCanvas = null;
...
blankCanvas = new Dog();

To help you to keep the correct path, define Animal as an abstract class
After all, what does an instance of Animal represent?

Upvotes: 3

Alexander Galkin
Alexander Galkin

Reputation: 12524

The instance of your class once "born as animal" will live its life as an Animal. You can try to cast it to derived class, but since the instance itself remains Animal it will fail in all cases.

Here are some suggestions how you can change it to other class:

You can implement a custom conversion to another class by implementing it explicitly using a static methods, for example, you can implement something like:

public class Cat : Animal
{
 public Cat FromAnimal(Animal animal)
 {
   return new Cat(animal) {Eyes = Color.Blue, ... };
 }
}

You can serialize and then deserialize your instance using certain serializers that support deserializing in another class.

You can Implement deep cloning of your instance with explicit return types of derived types.

Then you just substitute your old Animal with a new-bord Cat and use it everywhere...

Upvotes: 0

Greg Harris
Greg Harris

Reputation: 114

As far as I know you can't do that with a cast, but you could have a constructor in Dog that would accept and animal as a parameter like this:

Public Dog(Animal pAnimal)
{
    //do stuff...
}

Upvotes: 0

Andrew Hare
Andrew Hare

Reputation: 351456

There is no way to do this without writing a custom conversion. Probably a better thing to do would be to decide much earlier what kind of derived type that you need and create an instance of that.

Most of the time when the type system is going to fight you in this way you need to redesign your architecture.

Upvotes: 1

Related Questions