将子对象转换为父对象
我需要能够将子对象的实例强制转换为父对象的实例。
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.
是否有另一种方式来施展它?
谢谢
问题是xml serialiser将具有子类型的对象序列化为根元素。 我真的不想将目标类型一直传递给序列化器。 有没有更好的办法? – 朱尔斯
我没有多次使用序列化,但我的猜测是你需要改变你在子元素中“我如何序列化自己”的定义,把它自己写出来就像是父母一样。
如果你想要实际拥有“父”的实例,那么你需要创建一个新的Parent并将Child中的所有值复制到该Parent。 (如果你有很多这样的话,我不会这样做,但是如果你没有那么多,那么它应该不是问题。)最简单的方法是在Parent中创建一个复制构造函数。 它将是一个构造函数,它将Parent作为参数并将参数复制到自身的值(在这种情况下为Name,我假设您可能已省略其他值)。 然后你可以创建一个新的Parent,传入Child作为参数(因为Child是一个Parent,不需要强制转换/转换),它会吐出一个实际的Parent实例。
你没有将演员分配给任何东西。
var myClass = new Child(); Parent p = (Parent)myClass;
编辑 – 我认为你误解了铸造是如何工作的。 Say Parent有一个virtual
方法, DoStuff()
在Child
中被覆盖。 即使你将myClass
为Parent
,它也会运行Child
的DoStuff
方法。 无论如何,即使你施展它, Child
也是Child
,永远是Child
。
如果您尝试将其传递给接受Parent
对象的方法,则不必强制转换它。 由于是一个Child
,它已经是Parent
了。
我想我们错过了一些东西。 你还想尝试什么? 什么不起作用?
这应该工作。
但是我怀疑你编写代码的方式是不是在新变量中捕获了转换对象? 试试这个:
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不会按照您的想法行事。
你可以使用as运算符…好的事情是没有exception将被抛出,如果“强制转换”失败,你可以检查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");
如果Parent
是Child
的超类,那么Child
自动也是Parent
(包含`Parent的所有属性和方法),您不需要强制转换。
此外,你不能只用一个演员开始一行。 你可以写一些例子
Parent p = (Parent)myClass;
刚刚遇到问题的变化,我想我已经有了一个非基于序列化的解决方案。
和OP一样,我有inheritance自A类的B类,我需要B.GetType()。返回的名称就像是A类一样。
在B类中,您需要重写GetType()以返回.GetType()。BaseType
那样B.GetType()总是看起来像A.GetType()
由于这是非常繁重的,并且我的所有类都inheritance自我自己的标准baseClass,因此我将向baseClass添加一个名为TypeName的属性,该属性返回this.GetType()。
然后在我想要看起来像它的父类的一个特殊类中,我将覆盖它以返回this.GetType()。BaseType.Name
然后在我的代码中,我将引用.TypeName而不是.GetType()。当我需要特殊的“掩盖”类的类型名称时,直接命名。假设我只使用.GetType()我需要忽略这个子类的一个区域,它对我自己的使用相当干净。
我遇到了同样的问题并提出了以下解决方案:
我的初始代码是这样的:
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 Customer() : base(); }
当我尝试将一个Person对象转换为客户时,我遇到了“cast fail”错误
而不是追求铸造的想法,我决定修改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); }
我在这里晚了五年,但……
您可以使用AutoMapper来解决您的问题。
只需定义父类和子类之间的映射。 最简单的地图就可以了。 在定义映射的类中:
CreateMap();
然后,在代码中的任何位置,您都可以:
Child child = new Child(); Parent parent = Mapper.Map(child);
并且您的parent
对象将是纯Parent
,没有child
对象属性。
正如其他人所说,铸造一个物体将保留其类型。 那只会改变指针。 但AutoMapper会创建目标类型的新实例,并将值从参数复制到目标类型的实例,按名称匹配属性。