2012-09-24 225 views
72

C#中是否可以將基類對象顯式轉換爲其派生類之一?目前認爲我必須爲接受基類對象作爲參數的派生類創建構造函數,並複製屬性值。我不太喜歡這個想法,所以如果可能的話,我想避免它。將基類轉換爲派生類

這似乎並不像它應該工作(對象實例化作爲新的基地,所以內存不應該被分配給派生類的額外的成員),但C#似乎讓我做到這一點:

class BaseClass 
{ 
    ... some stuff ... 
} 

class DerivedClass : BaseClass 
{ 
    public bool MyDerivedProperty{ get; set; } 
} 


static void Main(string[] args) 
{ 
    BaseClass myBaseObject = new BaseClass(); 
    DerivedClass myDerivedObject = myBaseObject as DerivedClass; 

    myDerivedObject.MyDerivedProperty = true; 
} 
+4

你會得到最後一行空REF例外。 – Erix

+0

已經在這裏解答:http://stackoverflow.com/questions/729527/is-it-possible-to-assign-a-base-class-object-to-a-derived-class-reference-with-a –

+1

你應該瞭解什麼時候適合使用「as」而不是常規演員。如果您在此處使用強制轉換,C#編譯器會告訴您,您所做的是錯誤的。 –

回答

57

不,沒有內置的方式來轉換你喜歡說的類。最簡單的方法是按照您的建議進行操作:創建一個DerivedClass(BaseClass)構造函數。其他選項基本上會自動將屬性從基礎複製到派生實例,例如,使用反射。

您發佈使用as將編譯,因爲我相信你已經看到,但會拋出一個空引用異常,當你運行它,因爲myBaseObject as DerivedClass將評估爲null,因爲它不是DerivedClass實例的代碼。

1

不,沒有內置轉換爲此。 你需要像你提到的那樣創建一個構造函數,或者其他一些轉換方法。

此外,由於BaseClass不是DerivedClass,因此myDerivedObject將爲null,並且上面的最後一行將引發null ref異常。

3

不,這是不可能的。唯一可能的方式是

static void Main(string[] args) 
{ 
    BaseClass myBaseObject = new DerivedClass(); 
    DerivedClass myDerivedObject = myBaseObject as DerivedClass; 

    myDerivedObject.MyDerivedProperty = true; 
} 
+5

這拋出一個NullReferenceException,所以不工作,因爲這說明 –

+0

謝謝你,其他答案沒有說如何拋出 –

+0

有時,一點點重新思考,可以避免重大問題。謝謝! – peter70

5

您可以自己實施轉換,但我不會推薦。如果您想要這樣做以擴展現有對象的功能,請查看Decorator Pattern

33

這是不可能的。但你可以用一個對象映射器像AutoMapper

例子:

class A 
{ 
    public int IntProp { get; set; } 
} 
class B 
{ 
    public int IntProp { get; set; } 
    public string StrProp { get; set; } 
} 

Global.asax中或應用程序的啓動:

AutoMapper.Mapper.CreateMap<A, B>(); 

用法:

var b = AutoMapper.Mapper.Map<B>(a); 

它通過易於配置一個流利的API。

7

我找到了一個解決方案,並不是說它是最好的,但它對我來說很乾淨,並且不需要對我的代碼進行任何重大更改。我的代碼與你的代碼看起來很相似,直到我意識到它沒有用。

我的基類

public class MyBaseClass 
{ 
    public string BaseProperty1 { get; set; } 
    public string BaseProperty2 { get; set; } 
    public string BaseProperty3 { get; set; } 
    public string BaseProperty4 { get; set; } 
    public string BaseProperty5 { get; set; } 
} 

我的派生類

public class MyDerivedClass : MyBaseClass 
{ 
    public string DerivedProperty1 { get; set; } 
    public string DerivedProperty2 { get; set; } 
    public string DerivedProperty3 { get; set; } 
} 

以前方法得到一個人口稠密的基類

public MyBaseClass GetPopulatedBaseClass() 
{ 
    var myBaseClass = new MyBaseClass(); 

    myBaseClass.BaseProperty1 = "Something" 
    myBaseClass.BaseProperty2 = "Something else" 
    myBaseClass.BaseProperty3 = "Something more" 
    //etc... 

    return myBaseClass; 
} 

之前,我想這一點,這給了我一個無法施放的錯誤

public MyDerivedClass GetPopulatedDerivedClass() 
{ 
    var newDerivedClass = (MyDerivedClass)GetPopulatedBaseClass(); 

    newDerivedClass.UniqueProperty1 = "Some One"; 
    newDerivedClass.UniqueProperty2 = "Some Thing"; 
    newDerivedClass.UniqueProperty3 = "Some Thing Else"; 

    return newDerivedClass; 
} 

我改變了我的代碼如下波紋管,它似乎工作,更有意義現在:

public MyBaseClass GetPopulatedBaseClass() 
{ 
    var myBaseClass = new MyBaseClass(); 

    myBaseClass.BaseProperty1 = "Something" 
    myBaseClass.BaseProperty2 = "Something else" 
    myBaseClass.BaseProperty3 = "Something more" 
    //etc... 

    return myBaseClass; 
} 

public void FillBaseClass(MyBaseClass myBaseClass) 
{ 
    myBaseClass.BaseProperty1 = "Something" 
    myBaseClass.BaseProperty2 = "Something else" 
    myBaseClass.BaseProperty3 = "Something more" 
    //etc... 
} 

public MyDerivedClass GetPopulatedDerivedClass() 
{ 
    var newDerivedClass = (MyDerivedClass)GetPopulatedBaseClass(); 

    newDerivedClass.UniqueProperty1 = "Some One"; 
    newDerivedClass.UniqueProperty2 = "Some Thing"; 
    newDerivedClass.UniqueProperty3 = "Some Thing Else"; 

    return newDerivedClass; 
} 

public MyDerivedClass GetPopulatedDerivedClass() 
{ 
    var newDerivedClass = new MyDerivedClass(); 

    FillBaseClass(newDerivedClass); 

    newDerivedClass.UniqueProperty1 = "Some One"; 
    newDerivedClass.UniqueProperty2 = "Some Thing"; 
    newDerivedClass.UniqueProperty3 = "Some Thing Else"; 

    return newDerivedClass; 
} 
+0

非常好!正是我想要的! thx:D –

+4

每次添加屬性時,您都必須編輯此屬性。所以對於其他人閱讀這個我建議你考慮使用組合 –