[英]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.