2011-06-10 74 views
2
abstract class A<T> where T:A<T> 
{ 
    public event Action<T> Event1; 
} 

class B : A<B> 
{ 
    //has a field called Action<B> Event1; 
} 

有沒有更好的方法來做到這一點?我想要基類中的東西(事件等)能夠使用子類的類型。最好的方法來引用我自己的類型

+0

要小心,一個基類不應該有直接的知識的它的子類,它變成一個討厭的一塊技術債務。在這種情況下,因爲它是一個通用的,它不是太糟糕,但只是一般。 – 2011-06-10 17:18:30

+1

難道你不是指'在哪裏T:A '? Eric Lippert已經寫過這樣的內容:http://blogs.msdn.com/b/ericlippert/archive/2011/02/03/curiouser-and-curiouser.aspx – 2011-06-10 17:35:05

回答

4

您使用的模式實際上並未實現您想要的約束。假設你想「模型的動物只能是與它自己的一種友好的東西」:

abstract class Animal<T> where T : Animal<T> 
{ 
    public abstract void GetFriendly(T t); 
} 

class Cat : Animal<Cat> 
{ 
    public override void GetFriendly(Cat cat) {} 
} 

我們是否已經成功實施所需的約束?

class EvilDog : Animal<Cat> 
{ 
    public override void GetFriendly(Cat cat) {} 
} 

現在一隻邪惡的狗可以與任何貓友好,而不會與其他邪惡的狗友好。

您想要的類型約束在C#類型系統中是不可能的。如果您需要類型系統強制執行的這種約束,請嘗試使用Haskell。

看我對這個問題的文章瞭解詳情:

http://blogs.msdn.com/b/ericlippert/archive/2011/02/03/curiouser-and-curiouser.aspx

+0

我認爲你指出了一個重要的限制,但依賴於根據實際要求,這可能會或可能不是一個嚴重的問題。例如,如果僅在自己的代碼庫中使用它,如果模式正確實現,則風格上可能很明顯。 – kvb 2011-06-10 23:31:04

+0

有趣的事情就是這個。我完全不同意。對於您認爲這種技術存在的問題有一個簡單的解決方案。 http://blog.theobjectguy.com/2011/06/curiously-recurring-template-pattern.html – TheObjectGuy 2011-06-22 02:36:51

1

你的工作得很好。事實上,它非常類似於你想要的界面實現者使用你的類型其他.NET接口和類型,如:

public class MyClass : IEqualityComparer<MyClass> 
{ 
    // From the interface IEqualityComparer 
    public bool Equals(MyClass other) { ... } 

    ... 
} 
0

由於A是抽象的,你可以從一個添加的抽象方法,A和調用它們, B,將被強制執行的方法,將是調用:

abstract class A<T> where T:A 
{ 
    public event Action<T> Event1; 
    public abstract void Method(); 

    public A(){Method();} 
} 

class B : A<B> 
{ 
    //has a field called Action<B> Event1; 
    public void Method(){ //stuff } 
} 

在B的實例,基類的構造函數會調用()方法,這是隻有B中實施,迫使B的實例被稱爲。

這允許A調用子類特定的方法,而不要求A具有兒童的特定知識。缺點是所有的孩子必須實施方法或將其重新提取給自己的孩子。