0

Class diagram for the code below: HoneyManufacturer class and NectarCollector class both extend Bee class. Bee class implements interface IWorker.

IWorker[] bees = new IWorker[8];
bees[0] = new HoneyManufacturer();
bees[1] = new NectarCollector();
bees[2] = bees[0] as IWorker;   // bees[2] is of type HoneyManufacturer, why?
bees[3] = bees[1] as NectarCollector;
bees[4] = IWorker;
bees[5] = bees[0];
bees[6] = bees[0] as Object;
bees[7] = new IWorker();

So I understand that the bees[4] and bees[7] lines won't compile because interfaces cannot be instantiated. I still have the following questions:

  1. For the bees[2] line, my understanding is that the "as" keyword converts bees[0] to IWorker type since HoneyManufacturer class extends Bee class which implements IWorker interface. But bees[2] is still of type HoneyManufacturer (I've checked in my program), why?

  2. For the bees[6] line, book says it will compile but it doesn't compile in my Visual Studio 2022. Why?

I've already read so many other posts about casting and type conversion but I cannot find the answer to my specific question.

Thank you so much for your help!


Edit 1: (since I couldn't reply too long as a comment)

Thank you so much for your answers, really really appreciate it!!!

So do you mean that bees[2] = bees[0] as IWorker is only casting the reference variable, but not the object?

I checked the type of bees[2] with this code afterwards and it returns TRUE for all three.

Console.WriteLine(bees[2] is Bee);
Console.WriteLine(bees[2] is HoneyManufacturer);
Console.WriteLine(bees[2] is IWorker);

I thought that bees[2] would've been converted to IWorker and thus no longer of type HoneyManufacturer. Is there any circumstance when we actually need to do something like bees[2] = bees[0] as IWorker?

The book I'm reading is Head First C# and this is an exercise on page 381. It asks me to pick out the lines that won't compile and gives the answer of the bees[4] line and the bees[7] line. Then it asks which values of i would make this evaluate to TRUE:

(bees[i] is Bee)

The answer given is 0, 1, 2, 3, 5, 6 and I didn't understand why bees[2] is Bee.


Edit 2: (since I couldn't reply too long as a comment)

So is it correct to understand it in the following way?

What bees[2] = bees[0] as IWorker is doing is that it takes the reference variable bees[0] (which points to an object of HoneyManufacturer type) and casts it to a reference variable of IWorker type, and then assigns it to bees[2]. So bees[2] is now a reference variable of IWorker type, but it still points to the same object that bees[0] points to, which is of HoneyManufacturer type. And this line is essentially redundant because bees[2] is a reference variable of IWorker type to begin with, due to the first line IWorker[] bees = new IWorker[8]; where an array of reference variables of IWorker type is created and given the name bees.

  • Does this answer your question? [Typecasting in C#](https://stackoverflow.com/questions/1339482/typecasting-in-c-sharp) – gunr2171 Mar 11 '22 at 19:27
  • There is no reason the `bees[6]` line would compile, given your code. – gunr2171 Mar 11 '22 at 19:28
  • Can someone help me please? I've already read so many other posts about casting and type conversion but I cannot find the answer to my specific question. – AlwaysLearning Mar 11 '22 at 20:51
  • "So do you mean that bees[2] = bees[0] as IWorker is only casting the reference variable, but not the object?" I would not word it in this exact way, but essentially, yes. The thing is, in C# (as well as in Java) you have no way of directly dealing with an actual object; you only access objects via pointers. Every single variable that looks like an object is never really an object, it is in fact always a pointer to an object. So, `bees[0]` is not an object, it is a pointer. So, casting that pointer promises that it points to an object of a certain type. – Mike Nakis Mar 12 '22 at 07:53
  • "Is there any circumstance when we actually need to do something like bees[2] = bees[0] as IWorker?" No, because `bees[0]` is already an `IWorker`. – Mike Nakis Mar 12 '22 at 07:55
  • Thank you so much again, Mike! I've been reading other resources online, but haven't been able to find the exact explanation I need. Your answers have been the most helpful, thank you so much for helping me! I think I understand now, but could you just check one more time and see if I got it correct? I couldn't write everything here, so it's added under "Edit 2" in the post. Thanks so much again!!! – AlwaysLearning Mar 12 '22 at 22:19

2 Answers2

1

Typecasts of reference types do not convert anything. (Typecasts of value types are a different story.)

A typecast of a reference type just acts as promise that the right-hand-side can be assigned to the left-hand side. You are giving this promise to the compiler, so that the compiler will agree to compile your code, and if the promise turns out to be false at runtime, you will be slapped with a type-cast exception.

So:

1: the "as" keyword does not convert bees[0] to IWorker type, it just promises that bees[0] can be assigned to a variable of IWorker type, which is an entirely redundant promise to give, since bees[0] is already of IWorker type. You say you checked in your program; how did you check? what did you find? what did you expect?

2: What book says that? Exactly what does the book say? The statement bees[6] = bees[0] as Object; could never possibly compile because you are promising that bees[0] is an Object, which is again an entirely redundant promise to give, since bees[0] is of course of type Object, but you cannot assign that to bees[6], because bees[6] expects an IWorker, not an Object. Even though IWorker can be assigned to Object, the opposite is not true: Object cannot be assigned to IWorker.

Mike Nakis
  • 56,297
  • 11
  • 110
  • 142
  • Thank you so so much for your answer, it's extremely helpful! I couldn't reply in this comment section, it was too long, so I added my reply to the original post. Could you take a look please? Thank you so much again! – AlwaysLearning Mar 11 '22 at 21:54
  • Thank you so much again, Mike! I've been reading other resources online, but haven't been able to find the exact explanation I need. Your answers have been the most helpful, thank you so much for helping me! I think I understand now, but could you just check one more time and see if I got it correct? I couldn't write everything here, so it's added under "Edit 2" in the post. Thanks so much again!!! – AlwaysLearning Mar 14 '22 at 07:57
  • Yes, everything you have written under "Edit 2" is correct. – Mike Nakis Mar 14 '22 at 08:11
  • Awesome to know! Thank you so much for checking and helping me!!! – AlwaysLearning Mar 14 '22 at 17:42
0

There is needless convolution here with the array. I think you could use a bit of practice with inheritance and interfaces, and "is" and "as".

Check out this example I wrote up: https://dotnetfiddle.net/f37jNX