In the following simplified example, I need to abstract Collection classes in such a way that PrintFruitsAndEaters(oranges, orangeEaters);
or PrintFruitsAndEaters(apples, appleEaters);
becomes possible:
abstract class Fruit
abstract class FruitEater
class Apple : Fruit
class AppleEater : FruitEater
class Orange : Fruit
class OrangeEater : FruitEater
class AppleCollection : List<Apple>
class OrangeCollection : List<Orange>
class AppleEaterCollection : List<AppleEater>
class OrangeEaterCollection : List<Oran开发者_运维知识库geEater>
I've tried templatizing the method and collection classes, but i need to access methods specific to Fruit and FruitEater classes:
class FruitCollection<T> : List<T>
class FruitEaterCollection<T> : List<T>
void PrintFruitsAndEaters<T, S>(FruitCollection<T> fruits, FruitEaterCollection<S> eaters)
Then you want this:
void PrintFruitsAndEaters<T, S>(
FruitCollection<T> fruits,
FruitEaterCollection<S> eaters)
where T : Fruit
where S : FruitEater
{
// ...
}
This will constrain the T
and S
types as you require; calling the method with a FruitCollection<T>
, where the T
cannot be guaranteed to be Fruit
or a subtype, will result in a compile-time error. Same with S
and FruitEater
.
Because of the constraint, when working with a value of type T
you will be able to access members of the Fruit
class, and when working with a value of type S
you will be able to access members of the FruitEater
class.
Note that, as per Brian's (deleted) answer, you might want to add constraints to the collection types too:
class FruitCollection<T> : List<T> where T : Fruit { }
class FruitEaterCollection<T> : List<T> where T : FruitEater { }
But this will still not allow you to omit the constraints on the method.
(Also, inheriting List<T>
is an evil thing to do, instead use IList<T>
)
精彩评论