Why not generic derived type should specify type parameter for C # base base class

In Pro C # by Andrew Tolson, the author says that when a non-generic class extends a generic base class, the derived class must specify a type parameter.

// Assume you have created a custom
// generic list class.
public class MyList<T>
{
  private List<T> listOfData = new List<T>();
}
// Non-generic classes must specify the type
// parameter when deriving from a
// generic base class.
public class MyStringList : MyList<string>
{}

      

What I don't understand, why is this necessary?

+3


source to share


5 answers


Well, not generic classes have no type parameters, but generic classes have one or more type parameters.

If you inherit a class from a generic class without specifying a type parameter, you still have a generic class, ie

public class MyList<T> : List<T> {} //MyList is still generic

      

but

public class MyList : List<T> {} //invalid declaration, what is T ?

      

So

public class MyStringList : List<string> {} //specified with string

      

or, more generally

public class MyArrayList : List<object> {} //specified with object

      




A more verbose explanation, mainly because I like to use the word arity . "

Classes in the CLR can have an arity of zero or more, which means they can specify zero or more type parameters. However, the CLR cannot create classes with nonzero arity, so in order to do anything useful, the arity of the class must be reduced to zero.

This means that while we can partially specify classes such as:

public class IntKeyDictionary<TValue> : Dictionary<int, TValue>

      

which reduce arity or even declare classes like

public class ListAndAHalf<TOne, TTwo> : List<TOne>

      

which increase arity, the story must end with a class with arity 0, for example List<string>

, Dictionary<int, double>

etc ...

+4


source


Because it isn't used otherwise, because the CLR still doesn't know which type to use for T

.

List<T>

is public because it T

hasn't been replaced by an instance of the type yet. And you cannot instantiate public types. You can instantiate a type when it is closed , i.e. When all of its type parameters (including enclosing types and base types) have been replaced with instances of.



If you can declare class MyTList : MyList<T> { }

, then you will never be able to specify a type for T

because it MyTList

no longer includes that type parameter, so you can never instantiate MyTList

. This is not a very useful class.

+7


source


If you do not specify a type, the only other option is to generate a derived class as well.

public class MyDerivedList<T> : MyList<T>
{
}

      

+5


source


What if it isn't?

Yours MyStringList

would be generic (since T

there would be no hard-coded type for), but that is not by definition, as you are creating a non-generic class.

+2


source


Think about it the other way around. If you didn't provide a type parameter for your base type, which type should you use MyList<T>

? It will be undefined.

You can create a generic type that inherits from another generic type, and then you don't need to specify a supertype type parameter; your clients can do it.

+2


source







All Articles