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.

Answers


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. 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? So why shouldn't it be eligible to be a 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. 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.


It works because there's no reason why it wouldn't work. EntityBase<PersonEntity> doesn't inherit from PersonEntity, it merely references the type. 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
{
}

Need Your Help

Redraw scrollView and its contents for landscape orientation

objective-c uiscrollview orientation

I have a simple page with a nav bar at the top, tab bar at the bottom, and a scrollview filling the space between. The scrollview contains a label and image and a non-scrollable textview that gets

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.