通用继承规则
在 C# 中继承泛型类型类时,您需要遵循额外的规则。请记住,您的基类和派生类可以使用不同的泛型类型或共享它们。以下测试帮助我理解了规则。泛型类可以从具体、封闭构造或开放构造的基类继承,如下所示:
// 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 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 Derived6<T> : BaseType2<T> where T : struct { }// YES!
class Derived7<T> : BaseType2<string> 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!