user492922
user492922

Reputation: 935

Self-referential generic class templates

Is it possible to build the following heterogeneous (generic) linked list data type?

 class MyClass<TPrev, TNext> 
      where TNext : MyClass<TPrev2, TNext2> 
           where TPrev2 : MyClass<TPrev, TNext>

edit: Notice in particular the new type TNext2 which is not defined.

edit2: ... which makes the above snippet non-functional as written.

Upvotes: 2

Views: 1390

Answers (3)

Schmalls
Schmalls

Reputation: 1474

Take a look at this blog entry for an interesting idea on the topic. In essence you could do something like this:

public abstract class LinkedListBase<T>
    where T : LinkedListBase<T>
{
    public T Next { get; set; }
    public T Previous { get; set; }
}
public class LinkedListImpl : LinkedListBase<LinkedListImpl>
{
    public string Name { get; set; }
    // all of the value properties go here...
}

So essentially the value itself contains the links to the previous and next.

Upvotes: 0

munificent
munificent

Reputation: 12364

No, you can't model what you want. You could do this:

class Link<TPrev, TValue, TNext>
{
    public TPrev  Prev { get; set; }
    public TValue Value { get; set; }
    public TNext  Next { get; set; }
}

But you can't do:

class Link<???, TValue, ???>
{
    public Link<???> Prev { get; set; }
    public TValue Value { get; set; }
    public Link<???> Next { get; set; }
}

The problem is that if you declare that the previous and next elements of your list must also be lists of some generic type, then you've attempted to define a type of infinite size. There's no way to say, "There is no next node after this" because the next node must be a Link<T> for some other link type and you run into an infinite regress.

Upvotes: 2

jason
jason

Reputation: 241641

No, this is not possible because you haven't defined TNext2 or TPrev2 as part of the class definition. You can't have a generic parameter like that unless its an existing type, or is a generic type parameter in the class definition.

But then, if TPrev2 is an existing type, you can't specify a constraint on it like you are trying to do.

Upvotes: 0

Related Questions