RÈGLES GÉNÉRIQUES D'HÉRITAGE
Il existe d'autres règles que vous devez suivre lorsque vous héritez de classes de type générique en C#. N'oubliez pas que vos classes de base et dérivées peuvent utiliser des types génériques différents ou les partager. Les tests suivants m'ont aidé à comprendre les règles. Les classes génériques peuvent hériter de classes de base concrètes, construites fermées ou construites ouvertes comme suit :
// First create some Base Classes to inherit from.
// Non-generic and generic classes are included.
// Below, I will inherit these in Derived Classes.
// If my inheritance test works, you will see "YES", otherwise "NO".
class BaseType1 { }
class BaseType2<T> { }
class BaseType3<T1,T2> { }
// -------------------------------------------------
// Concrete type inheritance. Here the inheriting type
// does NOT have to be generic as the child
class Derived1 : BaseType1 { }// YES!
class Derived2<T> : BaseType1 { }// YES!
// Open constructed type generic inheritance allows shared
// generic type inheritance.
class Derived3<T> : BaseType2<T> { }// YES!
// Closed constructed type inheritance. Note that what the child
// class accepts as far as types is different from what the
// parent accepts.
// This is allowed as each implements its own types and
// constraints on its members and the parent has defined its type.
class Derived4<T> : BaseType2<int> { }// YES!
// NO! Base type must know its accepted type if the child
// class is not accepting a generic "T" type as well.
class Derived5 : BaseType2<T> { }// NO!
// Another form that limits generic type. Note, here the first
// base type uses a reference type "string" that is different from
// what the derived child type uses, which is any "struct" type or
// int, etc. Because the base type is defined as "string" the
// child can define anything for its generic or not even use a generic.
// The "where" clause only affects the derived class type!
class Derived7<T> : BaseType2<string> where T : struct { }// YES!
class Derived6<T> : BaseType2<T> where T : struct { }// YES!
// NO! The "where" clause cannot be used to define the base class's type!
class Derived8 : BaseType2<T> where T : struct { }// NO!
// NO! "T1" and "T2"must be a concrete type again if the derived
// type doesn't use the same
class Derived9 : BaseType3<T1,T2>// NO!
// Here, both parent and child classes must accept one generic
// type for this to work.
class Derived10<T> : BaseType3<T,T> { }// YES!
// Each generic type must have unique names in the derived class
// AND match the base class names. That is why these fail.
class Derived11<T, T> : BaseType3<T1, T2> { }// NO!
class Derived12<name1, name2> : BaseType3<T1, T2> { }// NO!
class Derived13<T1, T2> : BaseType3<T1, T2> { }// YES!
// As long as one generic name matches between child and parent,
// this shared generic type on child and parent ok.
class Derived14<Tname,T2> : BaseType2<Tname> { }// YES!
// Again, the child class doesn't have to be generic if the base
// generic class has defined the types it accepts.
class Derived15 : BaseType3<string, int> { }// YES!
class Derived16<T1, T2> : BaseType3<string, int> { }// YES!
// Here, you can have the child class accept two generic types,
// while the parent uses its own explicit type.
class Derived17<T1, T2> : BaseType2<string> { }// YES!
// No, you need to define these using "where".
class Derived18<string, int> : BaseType1 { }// NO!
class Derived19<T1, T2> : BaseType1 where T1 : class where T2 : struct { }// YES!
// This generates an error. You cannot inherit a generic type.
class Derived20 : T {}// NO!