简体   繁体   中英

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

This DID NOT Work:

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

NEITHER DID THIS:

Made a clone method within Class 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

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

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:

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. Either use a custom attribute to decorate what you want to copy, or copy just all props/fields of 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:

     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.

If you do not want to code the copy method yourself, you could look at a tool like AutoMapper .

After playing around and reading everything I could get my eyes on, both of the above solutions by GvS and Jan work. However, the end result that I wanted to achieve is not to be forced to write out each member in the Copy methods.

Why: a) If the class is edited and another object is added, the copy method will have to be updated. 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.

c) It just doesn't "feel" right. (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. (it has been discussed on these boards a lot).

After getting the 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. 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. 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. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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