【发布时间】:2021-10-12 17:58:22
【问题描述】:
interface IFoo
{
public ICollection<ICollection<string>> GetWords();
}
class Foo : IFoo
{
public ICollection<ICollection<string>> GetWords()
{
return new List<List<string>>() { new List<string>() { "word" } };
}
}
不允许(“无法隐式转换类型...”)
当接口是根据接口(泛型?)定义的并且实现当然是使用类型的实现时,我怎样才能避免对所有内容进行类型转换。
我觉得实现者应该可以选择他们使用哪个实现 ICollection 来提供功能,这就是为什么我希望接口中的类型保持 ICollection 并且调用者可以知道他们正在使用一些ICollection,但接口不应该强制实现者使用ICollection 的某个实现,也不应该在任何地方处理(冗余?)显式子类型到超类型类型转换。
我正在使用泛型类型,在我的情况下我得到了错误:
无法将类型“System.Collections.Generic.Dictionary
”隐式转换为“System.Collections.Generic.Dictionary ”
我不相信传说中缺乏对协方差的支持是解释,如果是,请向我解释一下。我不同意cmets的解释:
interface ... 定义了
SomeBase的方法返回类型,并且派生类使用返回SomeDerived的方法覆盖。目前不支持
因为这个小提琴(没有嵌套的泛型)成功地做到了这一点:dotnetfiddle.net/qkpxN8
这个页面:https://docs.microsoft.com/en-us/dotnet/standard/generics/covariance-and-contravariance 也这么说
您可以将 IEnumerable 的实例分配给 IEnumerable 类型的变量。
【问题讨论】:
-
您的第二个代码示例只需将
public放在方法签名的开头即可编译。 dotnetfiddle.net/qkpxN8 -
@theonlygusti 我在链接中提供的minimal reproducible example 没有那个错误。请提供完整的minimal reproducible example 显示此类错误。
-
这能回答你的问题吗? Does C# support return type covariance? C# 9.0 将支持第一种语法
-
有很多场景你可以说完全符合 Liskov 的替换原则,但在 .NET 类型系统中是不允许的。 .NET 类型系统中的一条规则是,如果您的方法被声明为返回类型 X,则您可以返回 X 类型的值或从 X 下降的类型的值。这不包括嵌套的泛型类型, 而
List<List<string>>不继承自ICollection<ICollection<string>>,也不是那种类型。 -
好吧,你的类型甚至不兼容。您无法返回输入到
ICollection<ICollection<string>>中的List<List<string>>。为什么?因为这将允许调用者将 any 类型添加到外部列表中,只要该类型实现ICollection<string>,但您的底层实际集合只接受List<string>。所以,返回一个List<ICollection<string>>。