【问题标题】:Substitution of generic type's parameter泛型类型参数的替换
【发布时间】: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&lt;List&lt;string&gt;&gt; 不继承自ICollection&lt;ICollection&lt;string&gt;&gt;,也不是那种类型。
  • 好吧,你的类型甚至不兼容。您无法返回输入到ICollection&lt;ICollection&lt;string&gt;&gt; 中的List&lt;List&lt;string&gt;&gt;。为什么?因为这将允许调用者将 any 类型添加到外部列表中,只要该类型实现 ICollection&lt;string&gt;,但您的底层实际集合只接受 List&lt;string&gt;。所以,返回一个List&lt;ICollection&lt;string&gt;&gt;

标签: c# .net


【解决方案1】:

此代码已在 Visual Studio 中测试并正常运行。


public interface IFoo
{
    public ICollection<ICollection<string>> GetWords();
}

public class Foo : IFoo
{
    
    public ICollection<ICollection<string>> GetWords()
    {
        var list= new List< List<string>>() { new List<string> { "one", "two" }};
        ICollection<string> strings = new List<string>();
        ICollection<ICollection<string>> collection =new  List<ICollection<string>>();
         
        for (var i = 0; i < list.Count; i++)
        {
            for (var j = 0; j < list[i].Count; j++)
            {
                strings.Add(list[i][j]);

            }
             collection.Add(strings);
        }
    
        return  collection;
    }
}

在visual studio中测试过

static void Main()
{
    var foo = new Foo();
    var words = foo.GetWords();
     var json = System.Text.Json.JsonSerializer.Serialize(words);
}

json

[
["one","two"]
]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-11
    • 1970-01-01
    • 2012-11-29
    • 2019-05-04
    • 1970-01-01
    • 2017-10-06
    相关资源
    最近更新 更多