灵活使用IDictionary(带接口)

本文关键字:接口 IDictionary | 更新日期: 2023-09-27 17:59:08

我正在尝试在我的一种方法中灵活地使用 IDictionary 接口,但由于转换方面的限制(请参阅 C# 类型转换:显式强制转换存在但抛出转换错误?(,它的使用对我来说非常有限。我想知道是否有一些解决方法。

这是我的具体问题:我有一个方法,它采用映射,将每个键映射到 IE无数其他键。它还需要一个键作为输入。它的作用是找到有关映射的给定键的闭包集/船体:

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]一起放入闭包集中。然后添加1234的图像,所以我们也得到了7(以及2图像的元素(。在下一步中,123的所有图像、47已添加,但它们已经在那里。因此,该方法结束并返回。

如您所见,这是一个非常抽象的方法,并不关心值到底是什么。它只需要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>>,因为我需要一些HashSetList的功能,而不是 IEnumerable 提供的功能。只是后来我想得到关闭。但是就像现在一样,我不能foobar作为我的方法的输入 - 我需要从它们创建新的词典以适应类型。

关于如何解决问题的任何想法(我不认为"创建新词典以适应类型"是一种解决方案(?

灵活使用IDictionary(带接口)

解决此问题的最佳方法是对公共 API 进行轻微更改。 从根本上说,GetClosureSet不需要将所有键映射到该键的值序列,它只需要一个操作来获取给定键的所有值:

public static ISet<T> GetClosureSet(
    T element, 
    Func<T, IEnumerable<T>> childSelector)

调用方可以通过多种方式实现该方法,其中一种方式是在他们拥有的字典中执行查找。 这实际上使您的方法更加通用,因为它允许您对存储其节点的不同类型的图执行此操作,例如"Node"对象,每个对象都已经引用了子项集合,而不是存储在字典中的图。

可以为集合类型添加参数:

public static ISet<T> GetClosureSet<T, C>(T element, IDictionary<T, C> elementToCollectionMap) where C : IEnumerable<T> { ... }

注意 编译器将无法为您推断C