引用我自己类型的最佳方式

本文关键字:最佳 方式 类型 我自己 引用 | 更新日期: 2023-09-27 17:59:04

abstract class A<T> where T:A<T>
{
    public event Action<T> Event1;
}
class B : A<B>
{
    //has a field called Action<B> Event1;
}

有更优雅的方法吗?我希望基类中的东西(事件等(能够使用子类的类型。

引用我自己类型的最佳方式

您使用的模式实际上并没有实现您想要的约束。假设你想模拟"一只动物只能对自己的同类友好":

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

您所拥有的功能非常好。事实上,它与其他.NET接口和类型非常相似,您希望接口实现者使用您的类型,例如:

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

我认为您不需要指定t:A的位置。

当你使用B类时,T将是B:

这也被称为CRTP或奇怪的重复模板模式,是一个已知的习语。

由于A是抽象的,您可以将抽象方法添加到A中,并从A和B中调用它们,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中实现的Method((,从而强制调用B的实例。

这允许A调用子类特定的方法,而不需要A具有Children的特定知识。不利的一面是,所有的孩子都必须实现Method或将其重新抽象为自己的孩子。

我最近的问题被标记为这个问题的重复。我完全同意那件事。所以我来到这里是为了看看答案,并阅读埃里克关于这个问题的帖子(确实很有趣(。不能在编译时使用类型系统强制执行此操作,但可以在运行时执行。我实现这一点的方式是:

abstract class FooBase<T>
{
    protected FooBase()
    {
        if (typeof(T) != GetType())
        {
            throw new InvalidOperationException();
        }
    }
}

通过这样做,我们可以播下一只邪恶狗的种子,但那只狗在运行时会流产。