0

Hello I am newbie to C# and I'm trying to figure out the "implicit conversion" operation. I have a question about it:

    class Animal { }
    class Monkey : Animal { }

    Monkey m = new Monkey();
    Animal a = m; 
    m.GetType()
    [Submission#165+Monkey]
    a.GetType()
    [Submission#165+Monkey]

Monkey m2 = a;// this calls - Compiler Error CS0266. Cannot implicitly convert type 'Animal' to 'Monkey'. An explicit

conversion exists (are you missing a cast?)

I don't understand - if last code line throws an error CS0266, why does GetType method returns that "a" variable has a type "Monkey". If "a" variable is Animal how to find it out? By what method?

M.Y.Mnu
  • 718
  • 8
  • 22
UIxH
  • 3
  • 1
  • Dupe of Cast from Parent Class to Child Class : https://stackoverflow.com/questions/988658/unable-to-cast-from-parent-class-to-child-class – Drag and Drop Dec 08 '17 at 10:44

2 Answers2

2

GetType() is evaluated at runtime. The error you are getting is at compile time, which is before the program ever runs.

The compiler needs to ensure type safety with the information it has at compile time. Ensuring means making sure nothing can go wrong. Assigning an Animal to a Monkey is, in general, not safe, because a Tiger is also an animal, so you could theoretically end up assigning a tiger to a monkey typed variable.

You can tell the compiler that although the assignment isn't safe, you know what you are doing. You do this with an explicit cast:

Monkey m2 = (Monkey)a;

Here you are telling the compiler; "Hey, I know this isn't generally safe, but trust me, I know a is a Monkey".

The compiler will accept your promise but won't trust you fully, so a type check will be performed at runtime just to make sure, and if your promise is a lie, you'll get a runtime error.

InBetween
  • 32,319
  • 3
  • 50
  • 90
  • InBetween, Thank you for your reply!Any way I have one more question: As i undestand compiler reads the script from the top to the bottom. And when it reads last code line it can only know that "a" varible was declared as Animal and because code didn't not run yet it doesn't know that "a is Monkey" , and that's why it throws an exception. Am I right? – UIxH Dec 08 '17 at 11:20
  • @UIxH don’t worry about the order, in general it’s not relevant. What the compiler sees is a variable `a` typed `Animal` that is correctly initialized to *something*. That something (a `Monkey`) can only be known at runtime (it’s not a compile time constant), the compiler can’t reason anything more about it, except that the assignment is safe. Also, don’t confuse compile time errors with exceptions. Exceptions happen at runtime, you are getting a compile time error, those happen while compiling. – InBetween Dec 08 '17 at 11:37
  • @UIxH: The "top to bottom" argument is expecting too much of the compiler. The compiler doesn't evaluate the entire program just to validate your one line of code. It validates the one line based on a few predefined checks (do the types match? do all mentioned variables exist? are these methods/properties accessible?). Although _some_ of these checks include looking further than the one line of code (e.g. checking if the variables all exist), the check for **type mismatch** is only done for the line itself, without looking at preceding code. – Flater Dec 08 '17 at 11:45
  • @InBetween, that figures, thanks for making that clear for me. I didn't pay attention on the difference between excpetions and compile time errors, now I will. – UIxH Dec 08 '17 at 12:16
  • @Flater thak you, it become more clear about compiler working. – UIxH Dec 08 '17 at 12:19
1

The type of the variable is Animal, the compiler will not allow you to assign this to a Monkey because an Animal is not necessarily a Monkey. You could assign the other way around because a Monkey is always an Animal. GetType() returns the runtime type of the object the variable points to which the compiler does not, and cannot, know anything about.

thisextendsthat
  • 1,266
  • 1
  • 9
  • 26
  • Thanks for answering, thisextendsthat! Any way I have one more question: As i undestand compiler reads the script from the top to the bottom. And when it reads last code line it can only know that "a" varible was declared as Animal and because code didn't not run yet it doesn't know that "a is Monkey" , and that's why it throws an exception. Am I right? – UIxH Dec 08 '17 at 11:25