C# 具有IDictionary和IEnumerable的嵌套泛型

C# 具有IDictionary和IEnumerable的嵌套泛型,c#,C#,在内部可重用库的通用C#类中,我想传递对“映射到其他事物列表的事物”的引用。库不应该知道传入的数据类型。此外,它们的存储方式也不应为人所知,即今天存储在内存中的列表可能是一个按需读取的数据库表 所以我想我应该写这个库类: class GenericClass<T, U> { public void Foo(IDictionary<T, IEnumerable<U>> bar) { // do something } }

在内部可重用库的通用C#类中,我想传递对“映射到其他事物列表的事物”的引用。库不应该知道传入的数据类型。此外,它们的存储方式也不应为人所知,即今天存储在内存中的列表可能是一个按需读取的数据库表

所以我想我应该写这个库类:

class GenericClass<T, U>
{
    public void Foo(IDictionary<T, IEnumerable<U>> bar)
    {
        // do something
    }
}
class泛型类
{
公共void Foo(IDictionary bar)
{
//做点什么
}
}
这会编译,但尝试传入具体实现不会:

class UsingClass
{
    public static void Main(string[] args)
    {
        var c = new GenericClass<string, string>();
        c.Foo(new Dictionary<string, List<string>>());
    }
}
class使用class
{
公共静态void Main(字符串[]args)
{
var c=新的GenericClass();
c、 Foo(newdictionary());
}
}
我发现以下两个语法错误:

Filename.cs(46,13): error CS1502: The best overloaded method match for 'GenericClass<string,string>.Foo(System.Collections.Generic.IDictionary<string,System.Collections.Generic.IEnumerable<string>>)' has some invalid arguments
Filename.cs(46,19): error CS1503: Argument 1: cannot convert from 'System.Collections.Generic.Dictionary<string,System.Collections.Generic.List<string>>' to 'System.Collections.Generic.IDictionary<string,System.Collections.Generic.IEnumerable<string>>'
Filename.cs(46,13):错误CS1502:GenericClass.Foo(System.Collections.Generic.IDictionary)的最佳重载方法匹配具有一些无效参数
Filename.cs(46,19):错误CS1503:参数1:无法从“System.Collections.Generic.Dictionary”转换为“System.Collections.Generic.IDictionary”
List
替换
Foo()
声明中的
IEnumerable
修复了它,但这当然不是我想要的

这是否真的没有得到C#(4.0)的支持,或者我只是遗漏了一些明显的东西?你会建议什么解决方法?(我相信这之前已经讨论过很多,所以链接到精彩描述也不错。)


是的,我应该能够为此编写自己的助手类,但为什么我必须这样做?

是的,这确实不受支持。想象一下,您的Foo方法如下所示:

public void Foo(IDictionary<T, IEnumerable<U>> bar)
{
    T key = GetKeyFromSomewhere();
    bar[key] = new U[10]; // Create an array
}
这将允许您从字典中获取值,并隐式地将它们转换为
IEnumerable
。。。但是,您只能在字典中输入正确类型的值,而不能仅从
U
值构建它

从版本4开始,C#支持受限环境下的通用差异。例如,这在C#4(针对.NET 4时)中有效,但以前不会:

List<string> strings = new List<string>();
IEnumerable<object> objects = strings;
List strings=newlist();
IEnumerable对象=字符串;

有关通用方差的更多信息,请参阅主题的。准备好让你的大脑周期性地爆发。

Ehh,我不知道我是否同意。如果调用方真的有问题,他们必须做出一个突破性的假设,即当函数只承诺
IEnumerable
@siride:但是调用方已经传入了
字典时,他们将从字典中返回一个
列表。该类型的值保证始终与
列表
的赋值兼容。如果该方法试图将错误类型的值放入该字典中,那么它确实应该在某种程度上发出砰砰的一声,最好是在编译时。或者您不认为泛型集合中的类型安全性很重要吗?;)不管怎么说,这正是我想要的,我的代码现在可以按照预期编译和工作了。谢谢你,乔恩@siride:我宁愿被编译时限制而不是执行时类型安全问题所困扰:)
List<string> strings = new List<string>();
IEnumerable<object> objects = strings;