如何仅使用强类型键来处理I​​Dictionary?

时间:2017-03-16 16:22:15

标签: c# .net dictionary types polymorphism

我有一个带静态方法的类,它可以对几种不同类型的对象集合进行操作,并对它们采取适当的行动:

static void DoSomething(ICollection<TypeA> things)
{
    // Do something with TypeA elements
}

static void DoSomething(ICollection<TypeB> things)
{
    // Do something with TypeB elements
}

在我的代码的其他地方,有很多词典使用TypeATypeB作为键,并为其值使用各种类型。我最终收到了DoSomething(dictionary.Keys)的一些电话,我认为通过接受dictionary并将.Keys集合传递给适当的重载的方法会更好。{/ p>

如果我强烈输入字典,我似乎可以这样做:

static void DoSomething(IDictionary<TypeA,object> dictionary)
{
    DoSomething(dictionary.Keys);
}

但是我需要为它可能遇到的每个IDictionary<TypeA,TValues>重载一次,即使该方法不需要知道TValues的工作原理。

我似乎也可以接受通用IDictionary,但是必须将Keys重新设置为适当的类型:

static void DoSomething(IDictionary dictionary)
{
    DoSomething((ICollection<TypeA>) dictionary.Keys);
}

这看起来并不明智,因为使用不受支持的键类型的字典调用不会让编译器失望,我可能不得不依赖Reflection来选择正确的重载。

我错过了一个更好的选择吗?

2 个答案:

答案 0 :(得分:2)

您可以创建一个通用方法,接受字典值类型的类型参数:

doInBackground

答案 1 :(得分:0)

要做的最好的事情(如果你能控制TypeATypeB)就是让这两种类型都实现这样的界面:

interface IDoSomething
{
    void DoSomething();
}

...并将字典更改为Dictionary<IDoSomething, T>

然后你可以简单地遍历字典键并在每个键上调用DoSomething()

其他解决方案往往违反Open/Closed Principle。例如,如果您执行as Markus suggested,那么您可以使用这样的开关/ if系列语句:

if (key is TypeA)
    DoSomething<TypeA>(key);
else if (key is TypeB)
    DoSomething<TypeB>(key);
else
    throw new Exception();

这是代码气味,表明违反了这一原则。例如,当您需要将类型为TypeC的键放入字典时会发生什么?您必须记住更改此代码所在的位置(因此此代码不会因修改而关闭)。如果您忘记了那么它是运行时错误而不是编译错误。随着代码的扩展,问题变得越来越严重,因为这些switch / if语句开始在整个地方突然出现。

如果您无法让TypeATypeB实现相同的界面,那么可能还有另一种方法可以重构SOLID principles。如果您对此问题的背景有任何其他问题,我相信SO社区很乐意回答一个单独的问题。