3

考虑以下:

public class EntityBase<TEntity>
{
    public virtual void DoSomethingWhereINeedToKnowAboutTheEntityType()
    {
    }
}

public class PersonEntity : EntityBase<PersonEntity>
{
    public override void DoSomethingWhereINeedToKnowAboutTheEntityType()
    {
    }
}

我将它添加到代码中并运行它,它工作正常,但我很惊讶我可以继承一个定义基于继承类的类。

当我尝试它时,我期望它不会编译,或者一旦实际调用就会失败。

您可以使用界面执行类似的操作:

public interface IEntityBase<TEntity>
{}

public class PersonEntity : IEntityBase<PersonEntity>
{}

实际上,我已经使用界面将我的代码从前者切换到了后者,但我仍然很好奇为什么会这样。

4

3 回答 3

4

它之所以有效,是因为它没有理由不起作用。EntityBase<PersonEntity>不继承自PersonEntity,它仅引用类型。基类知道自己的派生类没有技术问题。这也有效(即使这个具体的例子是个坏主意):

public class A
{
    public B AsB()
    {
        return this as B;
    }
}


public class B : A
{
}
于 2012-08-17T12:15:44.873 回答
3

我很惊讶我可以继承一个定义基于继承类的类。

小心-您继承的是一个定义涉及任意Type, 的类。所有这些都是合法的:

class O : EntityBase<object>
class S : EntityBase<String>
class Q : EntityBase<Q>

您在定义中所说的EntityBase只是TEntity应该是一种类型-嗯,PersonEntity是一种类型,不是吗?那么为什么它不应该有资格成为一个TEntity?没有理由不这样做 - 所以它有效。

您可能关心定义的顺序,但请记住,在编译单元中,所有内容都“立即”定义 - 没有任何意义PersonEntity需要在其他任何东西(包括它自己!)可以引用它之前“编译” . 事实上,你甚至被允许

class A : EntityBase<B>
class B : EntityBase<A>

如果需要这样的事情,任何可以想象的“编译顺序”都无法工作。

于 2012-08-17T12:26:12.893 回答
1

一个非常简单的例子是通用接口IComparable<T>。通常,您可以这样实现它:

class MyClass : IComparable<MyClass> {/*...*/}

通用模板的这种实现只是说MyClass对象可以与其他MyClass对象进行比较。如您所见,心智模型没有问题。我可以很好地理解一个类的概念,它的对象可以在它们之间进行比较,而无需了解该类的任何其他内容。

这里的重点是模板参数只是由泛型类或接口使用,但它们根本不需要通过继承来关联。IComparable<MyClass>不继承自MyClass. 所以不存在循环。

于 2012-08-17T12:26:51.550 回答