using System.Collections.Generic;
using System.Linq;
给定一个基类和两个派生类:
class Base{}
class Derived0 : Base{}
class Derived1 : Base{}
我有两个类型的词典:
IDictionary<String, Derived0> d0 = ...;
IDictionary<String, Derived1> d1 = ...;
我想找到两个词典的联合,它应该有IDictionary<String, Base>
类型。 (我已经知道两个词典中的键都是唯一的,所以当重复时我不关心行为。)
如果它们属于同一类型I could use
var union = d0.Concat(d1);
但这会产生错误(使用dmcs
进行编译):
Test.cs(15,20): error CS0411: The type arguments for method `System.Linq.Queryable.Concat<TSource>(this System.Linq.IQueryable<TSource>, System.Collections.Generic.IEnumerable<TSource>)' cannot be inferred from the usage. Try specifying the type arguments explicitly
如果我明确地将Base
作为类型参数:
IDictionary<string, Base> union = d0.Concat<Base>(d1);
它仍然不起作用:
Test.cs(15,42): error CS1928: Type `System.Collections.Generic.IDictionary<string,Derived0>' does not contain a member `Concat' and the best extension method overload `System.Linq.Enumerable.Concat<Base>(this System.Collections.Generic.IEnumerable<Base>, System.Collections.Generic.IEnumerable<Base>)' has some invalid arguments
/usr/lib/mono/gac/System.Core/4.0.0.0__b77a5c561934e089/System.Core.dll (Location of the symbol related to previous error)
Test.cs(15,42): error CS1929: Extension method instance type `System.Collections.Generic.IDictionary<string,Derived0>' cannot be converted to `System.Collections.Generic.IEnumerable<Base>'
原则上,方差应该不重要,因为我正在创建一个新的字典对象,但我无法弄清楚如何在类型系统中表示它。
答案 0 :(得分:3)
IDictionary<TKey, TValue>
和KeyValuePair<TKey, TValue>
不是变体......所以:
var sequence0 = d0.Select(kvp => new KeyValuePair<String, Base>(kvp.Key, kvp.Value));
var sequence1 = d1.Select(kvp => new KeyValuePair<String, Base>(kvp.Key, kvp.Value));
var dictionaryOfBase = sequence0.Concat(sequence1).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
答案 1 :(得分:0)
您可以使用以下扩展方法:
class Base { }
class Derived0 : Base { }
class Derived1 : Base { }
class Program {
static void Main(string[] args) {
var d0 = new Dictionary<string, Derived0>();
var d1 = new Dictionary<string, Derived1>();
var b = d0.Merge<string, Derived0, Derived1, Base>(d1);
}
}
public static class DictionaryExtensions {
public static Dictionary<TKey, TBase> Merge<TKey, TValue1, TValue2, TBase>(this IDictionary<TKey, TValue1> thisDictionary, IDictionary<TKey, TValue2> thatDictionary)
where TValue1 : TBase
where TValue2 : TBase {
var resultDictionary = new Dictionary<TKey, TBase>();
resultDictionary.AddRange(thisDictionary);
resultDictionary.AddRange(thatDictionary);
return resultDictionary;
}
public static void AddRange<TKey, TBase, TValue>(this IDictionary<TKey, TBase> dictionary, IDictionary<TKey, TValue> dictionaryToAdd) where TValue : TBase {
foreach (var kvp in dictionaryToAdd) {
dictionary.Add(kvp.Key, kvp.Value);
}
}
}