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

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

class A
{
     public int Foo{get; set;}
     public int Bar{get; set;}
}

class B : A
{
    public int Hello{get; 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;
    }
}

【问题讨论】:

    标签: c# inheritance


    【解决方案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 已为此用途创建。

    【讨论】:

      猜你喜欢
      • 2014-12-22
      • 1970-01-01
      • 1970-01-01
      • 2013-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-24
      相关资源
      最近更新 更多