我有以下代码
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)));
}
}
但是这不会编译,因为ToDictionary行会导致以下错误
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
现在很明显,MyTargetClass实现了ITargetClass,但是编译器没有选择它。
现在我明确转换(ITargetClass)新的MyTargetClass(v)
但是为什么这首先发生,是否有更好的方法来解决这个问题?
答案 0 :(得分:3)
编译器不会自动将IEnumberable<X>
转换为IEnumerable<Y>
即使X : Y
,因为IDictionary
不是covariant。这里讨论的理由如下:IDictionary<,> contravariance?和IDictionary<TKey, TValue> in .NET 4 not covariant
至于绕过它,就像你提到的那样,你必须施展:
使用Cast扩展方法:
kvp => kvp.Value.Select(v => new MyTargetClass(v)).Cast<ITargetClass>()
明确演员:
kvp => kvp.Value.Select(v => (ITargetClass) new MyTargetClass(v))
<强>更新强>:
由于IEnumerable
和IDictionary
之间的混淆,只是为了扩展这一点。 IEnumerable
是协变。 IDictionary
不是。
这很好:
IEnumerable<ITargetClass> list = new List<MyTargetClass>();
这不是:
IDictionary<object, IEnumerable<ITargetClass> dict =
new Dictionary<object, List<MyTargetClass>;
IDictionary
继承自IEnumerable<KeyValuePair<TKey, TValue>>
。问题是KeyValuePair
不是协变的,这使得IDictionary
不协变。
答案 1 :(得分:1)