Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Linq ToDictionary不会隐式地将类转换为接口_C#_Linq_Todictionary - Fatal编程技术网

C# Linq ToDictionary不会隐式地将类转换为接口

C# Linq ToDictionary不会隐式地将类转换为接口,c#,linq,todictionary,C#,Linq,Todictionary,我有以下代码 public class TestAdaptor { private interface ITargetClass { Guid Id { get; } string Name { get; } } private class MyTargetClass : ITargetClass { public Guid Id { get; private set; } public

我有以下代码

public class TestAdaptor
{
    private interface ITargetClass
    {
        Guid Id { get; }

        string Name { get; }
    }

    private class MyTargetClass : ITargetClass
    {
        public Guid Id { get; private set; }

        public string Name { get; private set; }

        public MyTargetClass(MySourceClass source)
        {
        }
    }

    private class MySourceClass
    {
        public Guid Id { get; set; }

        public string Name { get; set; }
    }

    private Dictionary<Guid, IEnumerable<ITargetClass>> ConvertItems(Dictionary<Guid, IEnumerable<MySourceClass>> source)
    {
        return source.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.Select(v => new MyTargetClass(v)));
    }
}
公共类测试适配器
{
私有接口类
{
Guid Id{get;}
字符串名称{get;}
}
私有类MyTargetClass:ITargetClass
{
公共Guid Id{get;private set;}
公共字符串名称{get;private set;}
公共MyTargetClass(MySourceClass源)
{
}
}
私有类MySourceClass
{
公共Guid Id{get;set;}
公共字符串名称{get;set;}
}
专用字典项(字典源)
{
返回source.ToDictionary(kvp=>kvp.Key,kvp=>kvp.Value.Select(v=>newmytargetclass(v));
}
}
但是,这不会编译,因为TODICTIONAL行会导致以下错误

Cannot implicitly convert type
'System.Collections.Generic.Dictionary<System.Guid,System.Collections.Generic.IEnumerable<TestAdaptor.TestAdaptor.MyTargetClass>>'
to
'System.Collections.Generic.Dictionary<System.Guid,System.Collections.Generic.IEnumerable<TestAdaptor.TestAdaptor.ITargetClass>>'   ...\TestAdaptor.cs  38  20
无法隐式转换类型
'System.Collections.Generic.Dictionary'
到
“System.Collections.Generic.Dictionary”…\TestAdaptor.cs 38 20
现在很明显,MyTargetClass实现了ITargetClass,但编译器没有接受这一点

目前,我正在显式转换(ITargetClass)新的MyTargetClass(v)


但是为什么会发生这种情况?有没有更好的方法来解决这个问题?

编译器不会自动将
IEnumerable
转换为
IEnumerable
,即使
X:Y
,因为
IDictionary
不是。这里讨论了这一点的基本原理:以及

至于绕开它,就像你提到的,你必须投下:

采用铸造延伸法:

 kvp => kvp.Value.Select(v => new MyTargetClass(v)).Cast<ITargetClass>()
更新

由于
IEnumerable
IDictionary
之间存在混淆,因此仅对其进行扩展<代码>IEnumerable是协变的<代码>IDictionary不是

这很好:

 IEnumerable<ITargetClass> list = new List<MyTargetClass>();
IEnumerable list=new list();
这不是:

 IDictionary<object, IEnumerable<ITargetClass>> dict = 
     new Dictionary<object, List<MyTargetClass>>();
IDictionary dict=
新字典();

IDictionary
继承自
IEnumerable
。问题在于
KeyValuePair
不可协变,这使得
IDictionary
不可协变。

Select只报告正在创建的对象,而不报告对象类型的一个方面。通过关键字让select知道您在使用什么

Select(v=>newmytargetclass(v)作为ITargetClass))

编译器的工作不是理解开发人员的
意图,因为一个类可以表达许多接口。必须为
select
语句提供提示,这最终使其与所需的返回对象保持一致

否则,您可以使用
IEnumerable
扩展来过滤元素并返回接口的IEnumerable,以返回方法所需的内容

.Select(v => new MyTargetClass(v))
.OfType<ITargetClass>()
。选择(v=>new MyTargetClass(v))
第()类

IEnumerable
是协变的……至少从.NET4开始是这样。@James-抓到了!我想写一本词典。更新的答案啊哈,所以协变是他们主要关心的问题,我想我可以用这种方式使用IEnumerbale而不会有麻烦。谢谢你的链接。我想真正的问题不是我应该显式地声明类型,而是在某些情况下我不必这样做,编译器实际上会理解所需的强制转换。这与LINQ无关,因为是字典本身导致了编译错误。我想我的困惑更多的是关于一致性,为什么我可以在一个案例(列表)中暗示类型,而在其他案例(字典)中却不能暗示类型。无论如何,飞利浦的回答解释了更多。无论如何,谢谢。@Kezza,只要你得到一个有效的答案,这才是最重要的。:-)
.Select(v => new MyTargetClass(v))
.OfType<ITargetClass>()