将子对象转换为父对象

时间:2012-01-31 15:19:51

标签: c#

我需要能够将子对象的实例强制转换为父对象的实例。

public class Parent 
{
 public string name{get;set;} 
}

public class Child : Parent{}

var myClass = new Child()
(Parent)myClass
//this doesnt seem to work and the object still has childs type.

还有另一种投射方法吗?

感谢

8 个答案:

答案 0 :(得分:11)

你没有将演员表分配给任何东西。

var myClass = new Child();
Parent p = (Parent)myClass;

编辑 - 我认为您误解了投射是如何运作的。假设父母有一个virtual方法,DoStuff()Child中被覆盖。即使您将myClass投射到Parent,它也会运行Child的{​​{1}}方法。无论如何,DoStuff都是Child,并且永远都是Child,即使你投了它。

如果您尝试将其传递给接受Child对象的方法,则不必强制转换它。由于是Parent,它已经是Parent

我认为我们错过了一些东西。你还想尝试什么?什么不起作用?

答案 1 :(得分:8)

这应该有效。

但我怀疑你编写代码的方式是否未在新变量中捕获转换对象?试试这个:

var myClass = new Child()
var myClassAsParent = (Parent)myClass;
// myClassAsParent still has the type "Child", but can be accessed as if it were a Parent.

修改 基于您已经离开的一些评论,我相信您误解了大多数编程语言的基本方面。就是这样:对象的类型无法改变。实例化为Child对象的对象将始终为Child对象

转换不会更改对象的类型。转换会改变程序其余部分“看到”对象的方式。如果愿意,它会更改对象的界面。因此,如果您将Child对象转换为Parent类型,程序的其余部分会认为它正在处理Parent类型,但它真的处理Child类型,使用一个非常糟糕的类比,穿着它的父母的衣服。

简而言之,Casting不会按照您的想法行事。

答案 2 :(得分:7)

  

问题是xml serialiser将子类型的对象序列化为   根元素。我真的不想一直传递我的目标类型   进入序列化器。有没有更好的办法? - 朱尔斯

我没有多次使用序列化,但我的猜测是你需要改变你在子元素中“我如何序列化自己”的定义,把它自己写出来就像是父母一样。

如果你想要实际拥有“父”的实例,那么你需要创建一个新的Parent并将Child中的所有值复制到该Parent。 (如果你有很多这样的话,我不会这样做,但如果你没有 那么多,那么这应该不是问题。)最简单的方法是在Parent中创建一个复制构造函数。它将是一个构造函数,它将Parent作为参数并将参数复制到自身的值(在这种情况下为Name,我假设您可能已省略其他值)。然后你可以创建一个新的Parent,传入Child作为参数(因为Child是一个Parent,不需要强制转换/转换),它会吐出一个实际的Parent实例。

答案 3 :(得分:1)

你可以使用as运算符......好的事情就是抛出没有异常,如果“强制转换”失败,你可以检查null。

public class Parent 
{
 public string name{get;set;} 
}

public class child : Parent{}

var myClass = new Child()
Parent foo  = myClass as Parent
if ( foo == null ) Debug.WriteLine("foo is NOT of type Parent");

答案 4 :(得分:1)

如果ParentChild的超类,则自动Child也是Parent(包含“父级”的所有属性和方法)需要施展。

此外,你不能只用一个演员开始一行。你可以写例如

Parent p = (Parent)myClass;

答案 5 :(得分:1)

刚刚遇到问题的变化,我想我已经有了一个非基于序列化的解决方案。

与OP一样,我有继承自A类的B类,我需要B.GetType()。返回的名称就像它是A类一样。

在B类中,您需要覆盖GetType()以返回.GetType()。BaseType

那样B.GetType()总是看起来像A.GetType()

由于这是非常繁重的,并且我的所有类都继承自我自己的标准baseClass,我将向baseClass添加一个名为TypeName的属性,该属性返回this.GetType()。Name

然后在我的一个特殊类中,我希望它看起来像是父类,我将覆盖它以返回this.GetType()。BaseType.Name

然后在我的代码中,我将引用.TypeName而不是执行.GetType()。当我需要特殊的“掩盖”类的类型名称时,直接命名。鉴于我只使用.GetType ()在我需要忽略这个子类的一个区域,它对我自己来说相当干净。

答案 6 :(得分:1)

我在这里已经晚了五年,但是......

您可以使用AutoMapper来解决问题。

只需定义父类和子类之间的映射。最简单的地图就可以了。在定义映射的类中:

CreateMap<Child, Parent>();

然后,在代码中的任何一点,您都可以:

Child child = new Child();
Parent parent = Mapper.Map<Parent>(child);

您的parent对象将是纯Parent,没有child个对象属性。

正如其他人所说,投射对象将保留其类型。这只会改变指针。但AutoMapper会创建目标类型的新实例,并将值从参数复制到目标类型的实例,按名称匹配属性。

答案 7 :(得分:0)

我遇到了同样的问题并提出了以下解决方案:

我的初始代码是:

public class Person
{
    public string Name { get; set; }

    public Person() {};
    public Person( Person rhs ) 
    {
        Name = rhs.Name;
    }
}

public class Customer : Person
{
    private string m_role = "Customer";
    public string Role { get m_role; }

    public Customer() : base();
}

public class Employee : Person
{
    private string m_role = "Employee";
    public string Role { get m_role; }

    public Employee() : base();
}

当我尝试将一个Person对象转换为客户时,我得到了#34;施放失败&#34;错误

而不是追求铸造的想法,我决定修改Child的复制构造函数,因此:

public class Customer : Person
{
    private string m_role = "Customer";
    public string Role { get m_role; }

    public Customer() : base();
    public Customer( Person per ) : base( per);
}

public class Employee : Person
{
    private string m_role = "Employee";
    public string Role { get m_role; }

    public Employee () : base();
    public Employee ( Person per) : base( per);
}