c# - 在 C# 中用泛型理解协变逆变的问题
问题描述
我不明白为什么以下 C# 代码无法编译。
如您所见,我有一个带有IEnumerable<T>
参数的静态泛型方法Something(并且T
被限制为IA
接口),并且该参数不能隐式转换为IEnumerable<IA>
.
解释是什么?(我不寻找解决方法,只是为了了解它为什么不起作用)。
public interface IA { }
public interface IB : IA { }
public class CIA : IA { }
public class CIAD : CIA { }
public class CIB : IB { }
public class CIBD : CIB { }
public static class Test
{
public static IList<T> Something<T>(IEnumerable<T> foo) where T : IA
{
var bar = foo.ToList();
// All those calls are legal
Something2(new List<IA>());
Something2(new List<IB>());
Something2(new List<CIA>());
Something2(new List<CIAD>());
Something2(new List<CIB>());
Something2(new List<CIBD>());
Something2(bar.Cast<IA>());
// This call is illegal
Something2(bar);
return bar;
}
private static void Something2(IEnumerable<IA> foo)
{
}
}
我Something2(bar)
排队的错误:
参数 1:无法从 'System.Collections.Generic.List' 转换为 'System.Collections.Generic.IEnumerable'
解决方案
错误消息提供的信息不足,这是我的错。对于那个很抱歉。
您遇到的问题是协方差仅适用于引用类型这一事实的结果。
您现在可能会说“但是IA
是引用类型”。是的。但是你没有说T
等于 IA
。你说那T
是实现 IA
的类型,值类型可以实现接口。因此,我们不知道协方差是否会起作用,并且我们不允许它。
如果您希望协方差起作用,您必须告诉编译器类型参数是具有class
约束和IA
接口约束的引用类型。
错误消息确实应该说转换是不可能的,因为协方差需要保证引用类型,因为这是根本问题。
推荐阅读
- c++ - c++/catch2:来自单独测试目录的参考代码
- html - 使弹性项目兄弟姐妹具有相同的高度
- numpy - 不同维度的numpy数组的区别
- sql - SQL - 如何对 count(user_id) 进行排序?
- push-notification - salesforce 向 android 的 salesforce 推送通知
- javascript - kendo-react-ui :菜单未在 Select 事件中传递所选项目,有时在加载时抛出异常
- python - 使用 numpy percentile 为每一行获取不同的分位数
- nginx - 本地静态资产的nginx服务器端缓存
- ios - 故事板冲突iOS后的XML标签不匹配
- javascript - 如果条件不满足,则减少循环迭代