2011-06-10 77 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具有儿童的特定知识。缺点是所有的孩子必须实施方法或将其重新提取给自己的孩子。