c# - 泛型与继承 : What am I doing wrong here?

标签 c# inheritance .net-3.5 casting polymorphism

声明了以下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/

相关文章:

c# - Format Decimal 2 Places - 无尾随零

java - 如果是父实例,instanceof 是否返回 true?

c++ - 在下面的程序中创建了多少个虚表?

java - 继承和调用方法(实例与非实例)

.net - AspNetCompiler MSBuild 任务中的 VirtualPath - 它是否必须等于最终部署的虚拟路径?

c# - 来自 httpResponse.end() 的缓冲输出?

c# - 您如何自动调整 DataGridView 控件中的列大小并允许用户调整同一网格上的列大小?

c# - 如何使用 FTP 在目录之间移动文件?

c# - Unity截图错误: capturing the editor too

.net - 如何通过串行连接有效地使用设备?