2010-05-27 83 views
5

我在C#中的類模板和類似的靜態方法來從靜態方法在派生類中創建通用類實例

class BClass<T> 
{ 
    public static BClass<T> Create() 
    { 
    return new BClass<T>(); 
    } 
} 

由此我得出一個類,並指定一個模板參數的基類

class DClass : BClass<int> { } 

當我嘗試使用靜態方法來創建d的實例出現問題

class Program 
{ 
    static void Main(string[] args) 
    { 
    DClass d = DClass.Create(); 
    } 
} 

給出編譯器錯誤「不能隱式轉換類型」Test.BClass < int>'to'Test.DClass'。「

將下面的cast添加到運行時轉換異常中。

DClass d = (DClass)DClass.Create(); 

是否有任何簡單的方法來允許靜態方法創建派生類的實例?理想情況下,我想要一個C++ typedef的等價物,我不想要下面的語法(它可以工作)。

BClass<int> d = DClass.Create(); 

回答

5

是有可能,通過具有類參考類型本身。請注意,在.NET世界中,我們談論的是泛型,而不是模板,它們的工作方式確實存在重要差異。

class BClass<T, TSelf> where TSelf: BClass<T, TSelf>, new() { 
    public static TSelf Create() { 
     return new TSelf(); 
    } 
} 

class DClass: BClass<int, DClass> {} 

class Program { 
    static void Main(string[] args) { 
     DClass d = DClass.Create(); 
    } 
} 
+0

沒有想到一個類可以在超類中引用自己作爲類型參數嗎?雞雞蛋佯謬或其他... – 2010-05-27 13:04:51

+0

聰明,有點奇怪! ;)我在這裏看到的唯一缺點是似乎永遠沒有辦法實例化一個普通的舊'BClass ',就像在OP的原始代碼中那樣。 – 2010-05-27 13:04:58

+0

@Peter,我實際上已經成功地使用了它。例如,它也允許你創建一個更好的克隆方法,因爲它消除了重新投射的需要等。 – Lucero 2010-05-27 13:13:17

7

看來,你想要的是用於DClass成爲BClass<int>的別名。但是,這不是你在這裏。你有什麼是DClass派生自BClass<int>。因此呼叫DClass.Create();創建了BClass<int>,這是而不是 a DClass(這是相反的方式)。

這可能會使它更清晰。假設你有如下層次:

class Rectangle { 
    static Rectangle Create() { 
     return new Rectangle(); 
    } 
} 

class Square : Rectangle { } 

// code elsewhere 
var shape = Square.Create(); // you might want this to return a square, 
          // but it's just going to return a rectangle 

一個選項得到的東西像你想可能是這樣定義你的Create方法的功能:

static TClass Create<TClass>() where TClass : BClass<T>, new() { 
    return new TClass(); 
} 

// code elsewhere 
var shape = DClass.Create<DClass>(); 

這是一個有點亂,但(也需要你爲DClass寫了一個無參數的構造函數)。如果你已經使用Create方法來實例化對象,可以考慮爲它寫一個工廠類。

1
class BClass<T> 
    { 
     public static T1 Create<T1, T2>() where T1 : BClass<T2>, new() 
     { 
      return new T1(); 
     } 
    } 

    class DClass : BClass<int> { } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      DClass d = DClass.Create<DClass, int>(); 
     } 
    } 
相關問題