简体   繁体   English

C# 继承。 从基类派生类

[英]C# inheritance. Derived class from Base class

I have a base class我有一个基类

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

I also have a derived class :我也有一个派生类:

public class B : A
{
    public string s3;
}

Suppose my program created an instance of class A.假设我的程序创建了一个类 A 的实例。

A aClassInstance = new A();

some parameters were set:设置了一些参数:

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

At this point I would like to create an instance of class B. But I would like B to already have the values of my instance of class A.此时我想创建一个类 B 的实例。但我希望 B 已经拥有我的类 A 实例的值。

This DID NOT Work:这不起作用:

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

NEITHER DID THIS:也没有这样做:

Made a clone method within Class A.在 A 类中创建了一个克隆方法。

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

The VS code takes both of the above - but I get run-time errors VS 代码采用上述两种方式 - 但我收到运行时错误

Please help请帮忙

The base problem you have is, that you have to construct an instance of type B (which contains of cause the properties of type A ).您遇到的基本问题是,您必须构造一个类型B的实例(其中包含类型A的属性)。 Your approach to clone an A instance won't work, because that gives you an instance of type A , which you can't convert to B .您克隆A实例的方法将不起作用,因为这为您提供了类型A的实例,您无法将其转换为B

I would write constructors for class A and B which takes a parameter of type A. The constructor of class B just passes the value to its base class A. The constructor of class A knows how to copy the fields to itself:我会为类 A 和 B 编写构造函数,它接受一个类型为 A 的参数。类 B 的构造函数只是将值传递给它的基类 A。类 A 的构造函数知道如何将字段复制到自身:

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

class B : A {

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

}

Use it this way:以这种方式使用它:

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

B b = new B(a);

EDIT编辑

When you don't want to have to change the constructor of A when adding new fields or props, you could use reflection to copy the properties.如果您不想在添加新字段或道具时更改A的构造函数,则可以使用反射来复制属性。 Either use a custom attribute to decorate what you want to copy, or copy just all props/fields of 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));
    }
}

I havn't tried the code, but the point should become clear.我还没有尝试过代码,但这一点应该很清楚。

You could create a generic clone method in class A:您可以在类 A 中创建一个通用的克隆方法:

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

Or if you want to make the cloning extendable:或者,如果您想让克隆可扩展:

     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;
     }

You use it like this:你像这样使用它:

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

Please note: in your example, both the new A(), and the MemberwiseClone will create a new object of type A.请注意:在您的示例中,new A() 和 MemberwiseClone 都将创建一个类型为 A 的新对象。

If you do not want to code the copy method yourself, you could look at a tool like AutoMapper .如果您不想自己编写复制方法的代码,则可以查看AutoMapper 之类的工具。

After playing around and reading everything I could get my eyes on, both of the above solutions by GvS and Jan work.在四处玩耍并阅读我能看到的所有内容后,GvS 和 Jan 的上述两种解决方案都有效。 However, the end result that I wanted to achieve is not to be forced to write out each member in the Copy methods.但是,我想要实现的最终结果不是被迫在 Copy 方法中写出每个成员。

Why: a) If the class is edited and another object is added, the copy method will have to be updated.为什么: a) 如果编辑了类并添加了另一个对象,则必须更新复制方法。 If someone else updates the class, they may forget to do this.如果其他人更新了课程,他们可能会忘记这样做。

b) There may be a lot of members, and assigning them may be time consuming. b) 可能有很多成员,分配他们可能很耗时。

c) It just doesn't "feel" right. c) 它只是“感觉”不对。 (Probably because I am very lazy). (可能是因为我很懒)。

Fortunately, I am not the only one with the same thoughts.幸运的是,我并不是唯一一个有同样想法的人。 Found a very very easy solution via the ValueInjector.通过 ValueInjector 找到了一个非常简单的解决方案。 (it has been discussed on these boards a lot). (已经在这些板上讨论了很多)。

After getting the dll (http://valueinjecter.codeplex.com/documentation)得到dll后(http://valueinjecter.codeplex.com/documentation)

The code becomes:代码变成:

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


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

That's it :)而已 :)

Obviously you would have to include:显然,您必须包括:

using Omu.ValueInjecter;

And not forget to add it to the references.并且不要忘记将其添加到参考文献中。

You can also use a JSON serializer for example.例如,您还可以使用 JSON 序列化程序。 You add a static method to your child-class which could then be called like this:您向子类添加一个静态方法,然后可以像这样调用它:

var porsche = Porsche.FromCar(basicCar);

Here, "Porsche" is the child class and "Car" is the base class.这里,“Porsche”是子类,“Car”是基类。 The function would then look something like this:该函数将如下所示:

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...
}

The trick here is, that properties that are available in the child but not the base, will be created with their default value, so null usually, depending on the type of the property.这里的技巧是,在子项中可用但在基项中不可用的属性将使用其默认值创建,因此通常为 null,具体取决于属性的类型。 The deserialization also goes by the name of the property, so all properties are copied over.反序列化也按照属性的名称进行,因此所有属性都被复制。

I didn't test this code, but it should work, as I've done this once or twice before.我没有测试这段代码,但它应该可以工作,因为我以前做过一两次。 Hope it helps someone.希望它可以帮助某人。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM