C#继承。来自Base类的派生类

时间:2011-12-25 22:28:28

标签: c# inheritance polymorphism

我有一个基类

public class A   
{
    public string s1;
    public string s2;
}

我还有一个派生类:

public class B : A
{
    public string s3;
}

假设我的程序创建了一个A类实例。

A aClassInstance = new A();

设置了一些参数:

aClassInstance.s1 = "string 1";
aClassInstance.s2 = "string 2";

此时我想创建一个B类实例。但是我希望B已经拥有了我的A类实例的值。

这不行::

public B bClassInstance = new B():
bClassInstance = (B)aClassInstance;

没有这样:

在A类中制作克隆方法。

public B cloneA() {    
    A a = new A();
    a = (A)this.MemberwiseClone()
    return(B)a;
}

VS代码采用上述两种方法 - 但我得到了运行时错误

请帮忙

4 个答案:

答案 0 :(得分:28)

您遇到的基本问题是,您必须构造一个类型为B的实例(其中包含类型为A的属性)。克隆A实例的方法不起作用,因为它为您提供了A类型的实例,您无法将其转换为B

我会为类A和B编写构造函数,它接受类型A的参数。类B的构造函数只是将值传递给它的基类A.类A的构造函数知道如何将字段复制到自身:< / p>

class A {
    public A(A copyMe) {
        s1 = copyMe.s1;
        ...
    }

class B : A {

    public B(A aInstance) : base(aInstance) {
    }

}

以这种方式使用:

A a = new A();
a.s1 = "...";

B b = new B(a);

修改

如果您不想在添加新字段或道具时更改A的构造函数,则可以使用反射来复制属性。使用自定义属性来装饰要复制的内容,或者只复制A的所有道具/字段:

public A (A copyMe) {
    Type t = copyMe.GetType();
    foreach (FieldInfo fieldInf in t.GetFields())
    {
        fieldInf.SetValue(this, fieldInf.GetValue(copyMe));
    }
    foreach (PropertyInfo propInf in t.GetProperties())
    {
        propInf.SetValue(this, propInf.GetValue(copyMe));
    }
}

我没有尝试过代码,但重点应该是明确的。

答案 1 :(得分:9)

您可以在A类中创建通用克隆方法:

     public T Clone<T>() where T : A, new() {
          return new T() { a = this.a, b = this.b};
     }

或者,如果您想使克隆可扩展:

     public T Clone<T>() where T : A, new() {
          var result = new T();
          this.CopyTo(result);
          return result;
     }

     protected virtual void CopyTo(A other) {
          other.a = this.a;
          other.b = this.b;
     }

你这样使用它:

     A  a = new A();
     // do stuff with a
     // Create a B based on A:
     B b = a.Clone<B>();

请注意:在您的示例中,新的A()和MemberwiseClone都将创建A类型的新对象。

如果您不想自己编写复制方法,可以查看AutoMapper之类的工具。

答案 2 :(得分:2)

在玩完并阅读我可以看到的所有内容之后,GvS和Jan的上述两种解决方案都得到了解决。 但是,我想要实现的最终结果不是强制在Copy方法中写出每个成员。

为什么: a)如果编辑了类并添加了另一个对象,则必须更新复制方法。如果其他人更新了课程,他们可能会忘记这样做。

b)可能会有很多成员,分配这些成员可能会非常耗时。

c)它没有“感觉”正确。 (可能是因为我非常懒惰)。

幸运的是,我不是唯一有同样想法的人。通过ValueInjector找到了一个非常简单的解决方案。 (已经在这些板上进行了很多讨论)。

获取dll后(http://valueinjecter.codeplex.com/documentation)

代码变为:

A a = new A();
a.s1 = "...";


B b = new B();
b.InjectFrom(a);

就是这样:))

显然你必须包括:

using Omu.ValueInjecter;

不要忘记将其添加到参考文献中。

答案 3 :(得分:1)

例如,您还可以使用JSON序列化器。您将一个静态方法添加到您的子类中,然后可以这样调用它:

var porsche = Porsche.FromCar(basicCar);

在这里,“保时捷”是孩子类,“汽车”是基类。该函数将如下所示:

public class Porsche : Car
{
    public static Porsche FromCar(Car basicCar)
    {
        // Create a JSON string that represents the base class and its current values.
        var serializedCar = JsonConvert.SerializeObject(basicCar);

        // Deserialize that base class string into the child class.
        return JsonConvert.DeserializeObject<Porsche>(serializedCar);
    }

    // Other properties and functions of the class...
}

这里的窍门是,将使用默认值创建子级中可用但子级中不可用的属性,因此通常为null,具体取决于属性的类型。反序列化也使用属性的名称,因此将所有属性复制过来。

我没有测试此代码,但它应该工作,因为我之前已经做过一两次。希望对别人有帮助。