我正在尝试在我的一种方法中灵活使用IDictionary
界面,但由于转换的限制(请参阅C# type conversion: Explicit cast exists but throws a conversion error?),它的使用对我来说非常有限。我想知道是否有一些解决方法。
这是我的具体问题: 我有一个方法,采用映射将每个键映射到IEnumerable其他键。它还需要一个键作为输入。它的作用是找到关于映射的给定键的闭包集/外壳:
public static ISet<T> GetClosureSet(T element, IDictionary<T, IEnumerable<T>> elementToCollectionMap)
{
ISet<T> closure = new HashSet<T>();
closure.Add(element);
closure.UnionWith(elementToCollectionMap[element]);
int count = 0;
while (count != closure.Count)
{
count = closure.Count;
foreach (T elem in new HashSet<T>(closure))
closure.UnionWith(elementToCollectionMap[elem]);
}
return closure;
}
类型IDictionary<double, IEnumerable<double>>
的这种映射示例:
1 -> [2, 3, 4]
2 -> [3, 7]
3 -> [3]
4 -> [] // empty enumerable, i.e. array of length 0
5 -> [6]
6 -> [6]
7 -> []
如果我将密钥1
和此映射放入我的方法,我将获得[1, 2, 3, 4, 7]
:首先1
并将其图像[2, 3, 4]
放在一起设置到闭包集中。然后添加了1
,2
,3
,4
的图片,因此我们也得到了7
(作为{2
图片的元素{1}})。在下一步中,1
,2
,3
的所有图片
,4
,7
已添加,但它们已在此处。因此,该方法结束并返回。
如您所见,这是一个非常抽象的方法,它不关心值是什么。它只需要IEnumerable<T>
的值就可以调用UnionWith
。
但是现在我希望每当我有从键到某种键集合的映射时都能使用该方法!
我的代码中有一些我定义的地方
IDictionary<MyType, HashSet<MyType>> foo = new Dictionary<MyType, HashSet<MyType>>();
和
IDictionary<MyType, List<MyType>> bar = new Dictionary<MyType, List<MyType>>();
并且需要他们真正IDictionary<MyType, HashSet<MyType>>
和IDictionary<MyType, List<MyType>>
,因为除了HashSet
提供的功能之外,我还需要List
和IEnumerable
的某些功能。只是后来我想要关闭。但就像现在一样,我不能将foo
和bar
作为我方法的输入 - 我需要从它们创建新的词典以适应该类型。
关于如何解决问题的任何想法(我不考虑“创建一个适合该类型的新字典”解决方案)?
答案 0 :(得分:2)
您可以为集合类型添加参数:
public static ISet<T> GetClosureSet<T, C>(T element, IDictionary<T, C> elementToCollectionMap) where C : IEnumerable<T> { ... }
请注意,编译器无法为您推断C
。
答案 1 :(得分:2)
解决此问题的最佳方法是对您的公共API进行细微更改。从根本上说,GetClosureSet
不需要将所有键映射到该键的值序列,只需要一个操作来获取给定键的所有值:
public static ISet<T> GetClosureSet(
T element,
Func<T, IEnumerable<T>> childSelector)
调用者可以通过多种方式实现该方法,其中一种方法是在他们拥有的字典中执行查找。这实际上使您的方法甚至更多一般,因为它允许您在完全不同地存储其节点的不同类型的图形上执行此操作,例如每个已经具有对a的引用的“Node”对象儿童的集合,而不是存储在字典中的图表。