我学习了以下代码。我知道我不能隐含地将“父母”转换为“孩子”(但我可以反过来)。但是,我试图明确转换但无法使其工作。我认为孩子在转换为父母时应该丢失数据。
class Parent
{
int A=5;
}
class Child:Parent
{
int B=5;
int C=2;
}
Parent parent = new Parent();
Child ch = new Child();
ch=ch as Parent //or (Parent)ch;
答案 0 :(得分:4)
为什么你需要这样做?由于继承关系,Child
是 Parent
。在您需要Parent
的任何地方,您都可以传递Child
并且它应该有效(如果不是,则会违反Liskov Substitution Principle)。
您可以将Child
视为Parent
,如此:
Child ch = new Child();
Parent childAsParent = ch as Parent;
但是毫无意义......
使用as Parent
和(Parent)之间的区别在于您是否会收到错误。如果as
不是ch
的实例,则“安全”广告(使用Parent
)只会留给您null,在这种情况下它始终是{{1}}。如果无法完成演员,另一个将抛出InvalidCastException。
答案 1 :(得分:3)
ch
一个Parent
,没有必要进行投射
如果你测试这个表达式
bool isParent = ch is Parent
你会看到isParent = true
。您可以在不使用任何演员
ch
用作Parent
答案 2 :(得分:2)
您需要在投射时将类型设置为正确的类型...
Child ch = child as Parent; //Wrong
Child ch = (Parent)child; //Wrong
Parent p = child as Parent; //Correct
Parent p = (Parent)child; //Correct
var p = child as Parent; //Correct (var will end up being a Parent)
var p = (Parent)child; //Correct (var will end up being a Parent)
可以解释不同类型的演员here(StackOverflow问题)。
我认为孩子在转换为父母时会丢失数据。
这是一个不正确的假设。您不是“丢失”数据,但您正在更改类型,这会更改您可以访问的成员。将其更改回Child
,成员B
和C
仍然保留其值。
答案 3 :(得分:0)
问题是ch
是Child
,您正在尝试为其分配Parent
。您是否尝试用
Parent pa = ch as Parent;
答案 4 :(得分:0)
更改
Parent parent = new Parentk();
Child ch = new Child();
ch=ch as Parent //or (Parent)ch;
通过
Parent parent = new Parent();
Child ch = new Child();
parent=ch as Parent //or (Parent)ch;
您将子项转换为父项,但结果是子项
答案 5 :(得分:0)
将您的最后一行修改为
Parent castRef = ch as Parent;
Parent castRef = (Parent)ch;
前者是一个“安全演员”,它将检查ch是否实际上是父类型(或者是一个上级),如果是,则返回对Parent类的引用,否则返回null。这与as运算符一起使用(如if(ch是Parent)...)
后者是一个明确的演员而且没有检查,可能会让你引用一些不是(或从父亲那里退出)的东西,当你使用它时会出现奇怪的错误。
我总是更喜欢以前的版本。
并且明确回答你的问题;你需要一个新的父类型变量ref来分配强制转换。
答案 6 :(得分:0)
注意对象实例和引用之间的区别。
new Child();
实例化(创建)Child类的实例。这意味着现在有一个对象(在“堆”中),但是您没有对该对象的直接访问权限,您可以通过对它的引用进行间接访问。实例化对象后,您无法更改其类型。
Child ch;
定义了一个具有Child接口的引用,默认情况下引用没有对象(IE:null)
Parent parent;
定义具有Parent接口的引用。
一旦存在这些引用,您就可以使用以下行来将它们分配给对象:
parent = new Parent();
或
ch = new Child();
因为Child继承自Parent(正如其他人所说,它是“Parent”),所以Parent引用也可以引用Child对象。 IE:
parent = new Child();
或
parent = ch;
但您只能通过Parent引用访问Parent定义的Child对象部分。请注意,此时不需要演员表。但是,你需要一个转向另一个方向。也就是说,如果它仍然是一个Child对象,但到目前为止只有一个Parent引用,则需要一个强制转换来获取一个Child引用:
ch = (Child)parent;
或
ch = parent as Child;
如果无法执行演员,前者将抛出异常。如果无法执行强制转换,后者将为ch赋值。