如何显式转换类型(自定义类)

时间:2012-03-06 12:45:06

标签: c# inheritance

我学习了以下代码。我知道我不能隐含地将“父母”转换为“孩子”(但我可以反过来)。但是,我试图明确转换但无法使其工作。我认为孩子在转换为父母时应该丢失数据。

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;

7 个答案:

答案 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,成员BC仍然保留其值。

答案 3 :(得分:0)

问题是chChild,您正在尝试为其分配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赋值。