引用我自己类型的最佳方式
本文关键字:最佳 方式 类型 我自己 引用 | 更新日期: 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();
}
}
}
通过这样做,我们可以播下一只邪恶狗的种子,但那只狗在运行时会流产。