声明了以下4个对象:
abstract class AConfigAction {}
abstract class APlugin<ConfigActionType> where ConfigActionType :AConfigAction {}
class AppExecuteConfigAction : AConfigAction {}
class AppExecutePlugin : APlugin<AppExecuteConfigAction>{}
- 所有类(class)都是公开的。为简单起见,尸体已被移除。
为什么这个转换失败?
_plugins = new List<APlugin<AConfigAction>>();
_plugins.Add(new AppExecutePlugin()); <--- Error
cannot convert from 'AppExecutePlugin' to 'APlugin'
完整错误信息:
Error 1 The best overloaded method match for 'System.Collections.Generic.List>.Add(EnvironmentSwitcher.Model.ConfigAction.APlugin)' has some invalid arguments R:\projects\EnvironmentSwitcher\EnvironmentSwitcher\View\ConfigurationActionManagerForm.cs 35
Error 2 Argument '1': cannot convert from 'EnvironmentSwitcher.Model.ConfigAction.AppExecute.AppExecutePlugin' to 'EnvironmentSwitcher.Model.ConfigAction.APlugin' R:\projects\EnvironmentSwitcher\EnvironmentSwitcher\View\ConfigurationActionManagerForm.cs 35
最佳答案
让我们让它更容易理解:
abstract class Animal {} // was AConfigAction
abstract class Cage<T> where T : Animal {} // was APlugIn
class Tiger : Animal {} // was AppExecuteConfigAction
class TigerCage : Cage<Tiger>{} // was AppExecutePlugin
var cages = new List<Cage<Animal>>();
cages.Add(new TigerCage()); // Why is this an error?
假设这是合法的。是什么阻止了这一点?
class Shark : Animal {} // some other config action
...
var cages = new List<Cage<Animal>>();
cages.Add(new TigerCage());
Cage<Animal> firstCage = cages[0];
firstCage.InsertIntoCage(new Shark());
firstCage 的类型是 Cage<Animal>
这意味着它可以容纳任何种类的动物。但实际上我们知道那是只老虎的笼子。你只是把一条鲨鱼关进老虎笼子里,这对鲨鱼和老虎来说似乎都很不舒服。
显然这是不允许的。是什么阻止了它?唯一阻止它的是,首先将老虎笼子放入动物笼子集合是违法的。虎笼不是一种动物笼,因为有些事情你可以用动物笼做,而你不能用虎笼做,即把鲨鱼放进去它。面向对象设计的一个基本原则是子类型可以做它们父类(super class)型可以做的一切;虎笼不能做动物笼能做的所有事情,所以它不是亚型。
更夸张的说法是,不能使泛型类型在其类型参数中是协变的,因为这样做会违反 Liskov 替换原则。在 C# 4 中,某些接口(interface)和委托(delegate)的类型参数是协变的。例如,在 C# 4 中放置 IEnumerable<Tiger>
是合法的进入List<IEnumerable<Animal>>>
因为没有办法让它变得不安全。我们可以在允许协变的同时坚持替代原则,因为IEnumerable<T>
是一个“out-only”接口(interface)。你只会把老虎赶出去;没有办法把鲨鱼放进去。
关于c# - 泛型与继承 : What am I doing wrong here?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8689109/