c#继承和向下继承层次结构

Posted

技术标签:

【中文标题】c#继承和向下继承层次结构【英文标题】:c# inheritance and casting down inheritance hierarchy 【发布时间】:2011-06-16 11:41:33 【问题描述】:

我想从 A 类型的现有对象创建一个 B 类型的新对象。B 继承自 A。我想确保将 A 类型对象中的所有属性值复制到该对象B型。实现这一目标的最佳方法是什么?

class A

     public int Fooget; set;
     public int Barget; set;


class B : A

    public int Helloget; set;



class MyApp
    public A getA()
         return new A() Foo = 1, Bar = 3 ;
    

    public B getB()
         A myA = getA();
         B myB = myA as B; //invalid, but this would be a very easy way to copy over the property values!
         myB.Hello = 5;
         return myB;
    

    public B getBAlternative()
         A myA = getA();
         B myB = new B();

         //copy over myA's property values to myB
         //is there a better way of doing the below, as it could get very tiresome for large numbers of properties
         myB.Foo = myA.Foo;
         myB.Bar = myA.Bar;

         myB.Hello = 5;
         return myB;
    

【问题讨论】:

【参考方案1】:
class A 
    public int Foo  get; set; 
    public int Bar  get; set; 

    public A()  

    public A(A a) 
        Foo = a.Foo;
        Bar = a.Bar;
    


class B : A 
    public int Hello  get; set; 

    public B()
        : base() 

    

    public B(A a)
        : base(a) 

    

编辑

如果您不想复制每个属性,则可以使 A 和 B 可序列化并序列化您的 A 实例(例如流,而不是文件)并用它初始化您的 B 实例。但我警告你,这很恶心,而且开销很大:

A a = new A() 
    Bar = 1,
    Foo = 3
;

System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(typeof(A));
System.IO.Stream s = new System.IO.MemoryStream();
xs.Serialize(s, a);

string serial = System.Text.ASCIIEncoding.ASCII.GetString(ReadToEnd(s));
serial = serial.Replace("<A xmlns", "<B xmlns");
serial = serial.Replace("</A>", "</B>");

s.SetLength(0);
byte[] bytes = System.Text.ASCIIEncoding.ASCII.GetBytes(serial);
s.Write(bytes, 0, bytes.Length);
s.Position = 0;

xs = new System.Xml.Serialization.XmlSerializer(typeof(B));
B b = xs.Deserialize(s) as B;

您可以通过ReadToEndhere获取更多信息。

【讨论】:

感谢您添加序列化程序代码。我可能还可以使用反射来循环遍历所有成员并复制值,但这也会带来很多开销。【参考方案2】:

您可以为 B 定义显式转换运算符:

   public static explicit operator B(A a) 
   
     B b = new B();
     b.Foo = a.Foo;
     b.Bar = a.Bar;
     b.Hello = 5;
     return b;
   

那么你可以这样做:

B myB = (B)myA;

【讨论】:

这是对代码的一个很好的重构——我喜欢 B 负责从 A 转换它。我还可以为 B 创建一个接受 A 类型对象的构造函数。不幸的是它仍然需要依次移动每个属性的值。 虽然这可能会产生误导......没有必要覆盖强制转换运算符...... 我相信任何实现都需要复制每个值,因为从一个类移动到它的子类需要新的内存分配。给了+1,但我也认为这对于其他开发人员来说可能很难遵循。我个人会提供一个重载的构造函数来获取基类。【参考方案3】:

这在 OO 机制中是不可能的,但 AutoMapper 已为此用途创建。

【讨论】:

以上是关于c#继承和向下继承层次结构的主要内容,如果未能解决你的问题,请参考以下文章

C#继承设计模式问题

iOS10 UI教程子视图和父视图UI层次结构和Views继承

避免并行继承层次结构

当在其层次结构中具有菱形继承的类的多重继承时,函数的模糊继承

C++ 几何层次结构、类向上转换和继承

C#之密封类(详解)