简体   繁体   English

继承中的循环泛型类型 - 为什么它有效?

[英]Circular generic types in inheritance - why does it work?

Consider the following: 考虑以下:

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

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

I added this into code and ran it and it worked ok, but I'm surprised that I can inherit a class who's definition is based on the inheriting class. 我将它添加到代码中并运行它并且它工作正常,但我很惊讶我可以继承一个基于继承类定义的类。

When I tried it I was expecting either it not to compile, or to fail once actually called. 当我尝试它时,我希望它不是要编译,要么是在实际调用时失败。

You can do something similar with an interface: 您可以使用界面执行类似操作:

public interface IEntityBase<TEntity>
{}

public class PersonEntity : IEntityBase<PersonEntity>
{}

I've actually switched my code from the former to the later, using the interface, but I'm still curious why this works. 我实际上使用界面将我的代码从前者切换到后者,但我仍然很好奇为什么这样做。

It works because there's no reason why it wouldn't work. 它的工作原理是因为它没有理由不起作用。 EntityBase<PersonEntity> doesn't inherit from PersonEntity , it merely references the type. EntityBase<PersonEntity>不从PersonEntity继承,它只引用该类型。 There's no technical problem with a base class knowing about its own derived class. 基类知道自己的派生类没有技术问题。 This also works (even though this specific example is a bad idea): 这也有效(即使这个具体的例子是个坏主意):

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


public class B : A
{
}

I'm surprised that I can inherit a class who's definition is based on the inheriting class. 我很惊讶我可以继承一个基于继承类定义的类。

Careful - what you're inheriting is a class whose definition involves an arbitrary Type , is all. 小心 - 你继承的是一个类,其定义涉及任意Type ,就是全部。 All of these are legal: 所有这些都是合法的:

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

All you've said in the definition of EntityBase is that TEntity should be a type - well, PersonEntity is a type, isn't it? 你在EntityBase的定义中所说的只是TEntity应该是一个类型 - 好吧, PersonEntity是一个类型,不是吗? So why shouldn't it be eligible to be a TEntity ? 那么为什么它不应该有资格成为一个TEntity No reason why not - so it works. 没有理由不 - 所以它的工作原理。

You might be concerned about the order of definitions, but remember that within the unit of compilation, everything gets defined 'at once' - there's no sense in which PersonEntity needs to be compiled 'before' anything else (including itself!) can refer to it. 您可能会担心定义的顺序 ,但请记住,在编译单元中,所有内容都“立即”定义 - 没有任何意义,在其他任何东西(包括它自己!)之前需要编译PersonEntity可以引用它。 Indeed, you're even allowed 的确,你甚至被允许

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

for which no conceivable 'order of compilation' could work, if such a thing were needed. 如果需要这样的话, 那么没有任何可以想象的“汇编顺序”可以起作用。

A very simple example is the generic interface IComparable<T> . 一个非常简单的例子是通用接口IComparable<T> Usually, you implement it like this: 通常,您可以像这样实现它:

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

This implementation of the generic template is just saying that MyClass objects can compare to other MyClass objects. 通用模板的这种实现只是说MyClass对象可以与其他MyClass对象进行比较。 As you can see, there is no problem with the mental model. 如您所见,心理模型没有问题。 I can very well understand the concept of a class whose objects can compare between them without knowing anything else about the class. 我可以很好地理解一个类的概念,它的对象可以在它们之间进行比较而不需要知道关于该类的任何其他内容。

The main point here is that template parameters are just used by the generic class or interface, but they need not be related by inheritance at all. 这里的要点是模板参数只是由泛型类或接口使用,但它们根本不需要通过继承来关联。 IComparable<MyClass> does not inherit from MyClass . IComparable<MyClass>不从MyClass继承。 So there is no circularity. 所以没有循环。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM