簡體   English   中英

C# 繼承。 從基類派生類

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

我有一個基類

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 代碼采用上述兩種方式 - 但我收到運行時錯誤

請幫忙

您遇到的基本問題是,您必須構造一個類型B的實例(其中包含類型A的屬性)。 您克隆A實例的方法將不起作用,因為這為您提供了類型A的實例,您無法將其轉換為B

我會為類 A 和 B 編寫構造函數,它接受一個類型為 A 的參數。類 B 的構造函數只是將值傳遞給它的基類 A。類 A 的構造函數知道如何將字段復制到自身:

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

我還沒有嘗試過代碼,但這一點應該很清楚。

您可以在類 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>();

請注意:在您的示例中,new A() 和 MemberwiseClone 都將創建一個類型為 A 的新對象。

如果您不想自己編寫復制方法的代碼,則可以查看AutoMapper 之類的工具。

在四處玩耍並閱讀我能看到的所有內容后,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;

並且不要忘記將其添加到參考文獻中。

例如,您還可以使用 JSON 序列化程序。 您向子類添加一個靜態方法,然后可以像這樣調用它:

var porsche = Porsche.FromCar(basicCar);

這里,“Porsche”是子類,“Car”是基類。 該函數將如下所示:

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,具體取決於屬性的類型。 反序列化也按照屬性的名稱進行,因此所有屬性都被復制。

我沒有測試這段代碼,但它應該可以工作,因為我以前做過一兩次。 希望它可以幫助某人。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM