C#:使用 "as" 关键字将对象的类型转换为它实现的接口后,为什么其类型没有更改?



下面代码的类图:HoneyManufacturer类和NectarCollector类都扩展了Bee类。Bee类实现接口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();

所以我理解bees[4]和bees[7]行不会编译,因为接口无法实例化。我仍然有以下问题:

  1. 对于蜜蜂[2]线,我的理解是;作为";关键字将bees[0]转换为IWorker类型,因为HoneyManufacturer类扩展了实现IWorker接口的Bee类。但蜜蜂[2]仍然是蜜蜂制造商类型(我已经在我的程序中检查过了(,为什么?

  2. 对于bees[6]行,书中说它会编译,但它并没有在我的VisualStudio2022中编译。为什么?

我已经读了很多关于选角和类型转换的其他帖子,但我找不到我特定问题的答案。

非常感谢你的帮助!


编辑1:(因为我不能回复太长时间作为评论(

非常感谢你的回答,真的非常感谢!!!

那么,你的意思是bees[2] = bees[0] as IWorker只转换引用变量,而不是对象吗?

之后我用这个代码检查了蜜蜂的类型[2],它对所有三个都返回TRUE。

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

我原以为蜜蜂[2]会变成IWorker,因此不再是蜜蜂制造商。有没有什么情况下我们真的需要做bees[2] = bees[0] as IWorker这样的事情?

我正在读的书是Head First C#,这是381页的一个练习。它让我挑选出不会编译的行,并给出bees[4]行和bees[7]行的答案。然后它询问i的哪些值会使其评估为真:

(bees[i] is Bee)

给出的答案是0,1,2,3,5,6,我不明白为什么蜜蜂[2]是蜜蜂。


编辑2:(因为我不能回复太长时间作为评论(

那么,用以下方式来理解它是正确的吗?

bees[2] = bees[0] as IWorker的作用是获取引用变量bees[0](指向HoneyManufacturer类型的对象(,并将其强制转换为IWorker类型的引用变量,然后将其分配给bees[2]。因此,bees[2]现在是IWorker类型的引用变量,但它仍然指向bees[0]所指向的对象,即HoneyManufacturer类型的对象。这一行本质上是多余的,因为bees[2]一开始是IWorker类型的参考变量,这是由于第一行IWorker[] bees = new IWorker[8];创建了IWorker类型的引用变量数组并命名为bees

引用类型的类型转换不会转换任何内容。(价值类型的类型转换是另一回事。(

引用类型的类型转换只是承诺可以将右手边分配给左手边。您将此promise提供给编译器,这样编译器就会同意编译您的代码,如果promise在运行时为false,您将被抛出类型转换异常。

因此:

1:;作为";关键字并没有将bees[0]转换为IWorker类型,它只是承诺bees[0]可以分配给IWorker类型的变量,这是一个完全多余的承诺,因为bees[0]已经是IWorker类型了。你说你已经注册了你的程序;你是怎么检查的?你发现了什么?你期待什么?

2:那是哪本书说的?这本书到底说了什么?语句bees[6] = bees[0] as Object;永远不可能编译,因为您承诺bees[0]Object,这也是一个完全多余的承诺,因为bees[0]当然是Object类型,但您不能将其分配给bees[6],因为bees[6]需要IWorker,而不是Object。即使IWorker可以分配给Object,但事实并非如此:Object不能分配给IWorker

这里与数组有不必要的卷积。我认为您可以对继承和接口进行一些练习;是";以及";作为";。

看看我写的这个例子:https://dotnetfiddle.net/f37jNX

最新更新