c# - 使用约束作为类型传递泛型类型
问题描述
如果我有GenericClass
一个类型约束为 的where T : BaseType
,为什么我不能将它作为 传递GenericClass<BaseType>
?
class GenericClass<T> where T : BaseType
{
void Method()
{
new UtilityClass().Method(this);
}
}
class UtilityClass
{
internal void Method(GenericClass<BaseType> genericClass)
{
}
}
静态分析器错误:
Cannot convert from 'GenericsPoc.GenericClass<T>' to
'GenericsPoc.GenericClass<GenericsPoc.BaseType>'
我没想到会这样,因为UtilityClass<T>
必须T
继承自BaseClass
.
解决方案
这个问题每天都会被问到。再一次!
class Cage<T> where T : Animal
{
public void Add(T t) { ... }
}
现在你的问题是:为什么这是非法的?
Cage<Animal> cage = new Cage<Gerbil>();
因为这条线是合法的:
cage.Add(new Tiger());
Cage<Animal>
有一个方法Add
需要Animal
. ATiger
是一个Animal
所以必须是合法的。但这意味着我们只是把老虎关进了沙鼠笼。
由于该行必须是合法的并且会导致类型错误,因此其他一些行必须是非法的,现在您知道它是哪一行了。
您想要的功能称为通用协方差,它在 C# 中是合法的,当:
- 泛型类型是接口或委托
- 可变类型参数是引用类型
- 接口或委托已被标记为安全变化。
例如:
IEnumerable<Animal> animals = new List<Tiger>() { new Tiger() };
那是合法的。List<Tiger>
implements IEnumerable<Tiger>
,它是一个接口并标记为对协变安全,因此可以将其分配给IEnumerable<Animal>
.
您会注意到,无法将鸭子放入动物序列中,因此无法将鸭子放入老虎序列中。这就是我们知道协方差是安全的。
推荐阅读
- scala - 远程 Metastore db 不在不同 spark 应用程序之间共享 global_temp 数据库
- amazon-web-services - 在 AWS X-Ray 中为 lambda 函数和微服务创建单一服务映射
- google-chrome-extension - background.js 中的 sendResponse() 不会将数据发送到内容脚本
- jquery-select2 - 使用带有 Select2 的初始数据集,并且仅在用户键入字符时发送 Ajax 搜索
- asp.net - 即使在服务器上也没有显示详细的 500 错误消息
- ruby-on-rails - sassc bundler 错误:Gem::Ext::BuildError: ERROR: Failed to build gem native extension
- c# - 无法在同一个 Web 服务中使用我的第二个 Web 方法
- c# - 为什么 FormClosed 事件处理程序会被调用两次?
- python - 有人可以给我看一个好的阶乘代码吗?
- push-notification - ionic3中的后台推送通知