-1

So I can't figure this out for the life of me. And I have tried casting in multiple forms.

This is the parent.

    /// <summary>
    /// Colour Parent
    /// </summary>
    public class Colour
    {

        #region Public Fields

        public float R;
        public float G;
        public float B;
        public float A;

        #endregion Public Fields
    }

And this is the child. Which has pre defined variables. Meaning it has ALL the information it needs to downcast.

    /// <summary>
    /// Data strucutre extension of Base.Colour, Used for the variables stored inside the glow object in memory
    /// </summary>
    public class GlowStruct : Colour
    {
        public bool RWO  = true;
        public bool RWUO = true;
    }

I try to cast it with.

return Base.Blue as GlowStruct;

Base.Blue is a static member of the Colour class. Using the "is" returns false.

Not sure why you need the definition of Base.Blue seeing as its just numbers. I already mentioned it was a static class.

public static Colour Blue = new Colour { R = 0, G = 0, B = 255, A = 255 };
Offnix
  • 27
  • 6
  • 4
    Please add the code where `Base.Blue` is defined/declared – phuzi Jan 23 '19 at 13:17
  • We can't help you without the definition of Base.Blue – Marco Salerno Jan 23 '19 at 13:17
  • As Blue is a static member of Colour, it needs accessing via the class type not the class instance. As pointed out though, Blue is not a Colour, so the cast will result in null being returned - using (GlowStruct)Colour.Blue would cause an exception.. – PaulF Jan 23 '19 at 13:35

2 Answers2

6

A GlowStruct is a Colour, but that doesn't mean that a Colour is a GlowStruct.

If Blue is a of type Colour than you can't cast it to a GlowStruct directly because GlowStruct requires additional information that the Colour class simply doesn't have - that's why the is operator exists in the first place - to allow you to determine the type of an instance when you only have a reference of some base class or interface type.

In more general terms, a derived class is a specific type of it's base class, but a class is not a type of any of the classes that might derive from it - if that was the case, the entire type system would become redundant, since any type ultimately derive from object and therefor anything could be casted to anything else.

And as another example - a tiger is a kind of felidae (basically, cats), and all cats are mammals, and all mammals are animals, but that doesn't mean that any animal is a tiger, a cat, or even a mammal.

Translated to c#:

class Animal {} 
class Mammal : Animal {}
class Felidae : Mammal {}
class Tiger : Felidae {}

you can do something like this:

Animal myTiger = new Tiger();

var mammal = myTiger as Mammal;
var felidae = myTiger as Felidae;
var tiger = myTiger as Tiger;

but you if you try to do something like this -

Animal myTiger = new Animal();

var mammal = myTiger as Mammal; 
var felidae = myTiger as Felidae; 
var tiger = myTiger as Tiger; 

then mammal, felidae, and tiger would all be null, since an animal might be a viper, which is not a mammal, not a cat, and defiantly not a tiger.

Zohar Peled
  • 79,642
  • 10
  • 69
  • 121
  • 4
    No, it doesn't contain the `RWO` and `RWUO` fields, since it's of type `Colour`. btw, public fields are bad practice - you should be using properties instead. Another BTW, in c#, naming conventions for public members of a type are CamelCase, meaning the first letter of every word should be capitalized, anything else should be lower case, even when dealing with abbreviations and acronyms. – Zohar Peled Jan 23 '19 at 13:23
  • 1
    And one more BTW, Check out the types in System.Drawing - the .Net framework already provides a type for Color. – Zohar Peled Jan 23 '19 at 13:27
  • My colour class Does not work to the same degree that System.Drawing does. – Offnix Jan 23 '19 at 13:31
  • I just don't understand why this is an issue. The variables for the child class are already defined. It doesn't have to wonder about information that is already predefined. All i want to do is give the data from the red Colour to the child class so it can slap two booleans on the end of the class. How is this a difficult task??? – Offnix Jan 23 '19 at 13:40
  • I've added another example to my answer that I hope will clarify it better for you. – Zohar Peled Jan 23 '19 at 13:48
0

I still strongly believe after doing research that the neglect of downcasting is silly. Downcasting has a lot of practical uses, My colour classes were created to eliminate repetitive code, as I would have to create a brand new class with the same information as the colour class with two extra booleans to give the same information as a GlowStruct. This also means if I were to edit those colour classes in base those changes would also not be reflected in the glowStruct colours. In the end, I added a function to the Glowstruct class to inherit the information from the parent Colour class.

From what was said, a lot of people tried to explain why downcasting doesn't work. One of those reasons was that there's no way to dictate what information should be put in the empty fields that are only in the child class. If you create a new class object it automatically fills those fields with null. And it just seems silly that c# is not able to fill with null in these situations aswell.

 public class GlowStruct : Colour
    {
        public bool RWO { get; } = true;
        public bool RWUO { get; } = true;

        public void Inherit(Colour Parent)
        {
            R = Parent.R;
            G = Parent.G;
            B = Parent.B;
            A = Parent.A;
        }
    }

Thanks for the answers. But in the end, they did not actually answer my question.

Offnix
  • 27
  • 6
  • Well, that just how c# works. Perhaps other OOP languages allow direct casting from base to child, but c# doesn't. Moreover, it's not allowed to override implicit/explict operators to cast between classes that inherit from each other. You can create a constructor that takes an instance of the base class and populate the members of the current instance (like you did in your `Inherit` method), but that's about as close as it gets. – Zohar Peled Jan 24 '19 at 09:03