strange behaviour of "as" operator
Asked Answered
B

2

7

So I have the following code:

 /// <summary>
/// The 'Prototype' abstract class
/// </summary>
abstract class ColorPrototype
{
    public abstract ColorPrototype Clone();
}

/// <summary>
/// The 'ConcretePrototype' class
/// </summary>
class Color : ColorPrototype
{
    private int _red;
    private int _green;
    private int _blue;

    // Constructor
    public Color(int red, int green, int blue)
    {
        this._red = red;
        this._green = green;
        this._blue = blue;
    }

    // Create a shallow copy
    public override ColorPrototype Clone()
    {
        Console.WriteLine(
          "Cloning color RGB: {0,3},{1,3},{2,3}",
          _red, _green, _blue);

        return this.MemberwiseClone() as ColorPrototype;
    }
}

/// <summary>
/// Prototype manager
/// </summary>
class ColorManager
{
    private Dictionary<string, ColorPrototype> _colors =
      new Dictionary<string, ColorPrototype>();

    // Indexer
    public ColorPrototype this[string key]
    {
        get { return _colors[key]; }
        set { _colors.Add(key, value); }
    }
}

And in the main method I have:

ColorManager colormanager = new ColorManager();

// Initialize with standard colors
colormanager["red"] = new Color(255, 0, 0);

// User clones selected colors
ColorPrototype p1 = colormanager["red"].Clone();
bool isColor = p1 is Prototype.Color;
Color color1 = p1 as Color;

My question is why the variable p1 has type Color (isColor is true) if in the clone method I cast the result to ColorPrototype (return this.MemberwiseClone() as ColorPrototype;) ?

Reference: http://www.dofactory.com/net/prototype-design-pattern

Barnyard answered 14/10, 2016 at 10:0 Comment(3)
An instance of ColorPrototype is also a Color because ColorProtoype derives from Color. The same way that an Rectangle is still a Shape.Tripletail
@Tripletail color extends ColorPrototype, so Color is a ColorPrototype and not viceversa, unless I use contravariance, right?Barnyard
Sorry, I misread it as ColorPrototype : Color.Tripletail
H
1

if in the clone method I cast the result to ColorPrototype

Because even though you cast p1 to a ColorPrototype, the runtime type of p1 is still of type Color. Casting a reference type allows you to view a type T as type U, but it doesn't alter the underlying runtime type.

Horny answered 14/10, 2016 at 10:6 Comment(1)
Thank you. "Casting allows you to view a type T as type U, but it doesn't alter the underlying runtime type" made it clear to me. I will mark this as an answer in a few minutes.Barnyard
N
2

this.MemberwiseClone() returns you Color object. So p1 is actually a Color.

It does not matter if you upcast it to ColorPrototype. Its runtime type is still Color. This is the same as:

string s = "foo";
object o = s as object;
// runtime o type is still string
Naji answered 14/10, 2016 at 10:4 Comment(1)
yes, but you have after: as ColorPrototype so this is somehow a safe cast... So why is still a color?Barnyard
H
1

if in the clone method I cast the result to ColorPrototype

Because even though you cast p1 to a ColorPrototype, the runtime type of p1 is still of type Color. Casting a reference type allows you to view a type T as type U, but it doesn't alter the underlying runtime type.

Horny answered 14/10, 2016 at 10:6 Comment(1)
Thank you. "Casting allows you to view a type T as type U, but it doesn't alter the underlying runtime type" made it clear to me. I will mark this as an answer in a few minutes.Barnyard

© 2022 - 2024 — McMap. All rights reserved.