我有一个带静态方法的类,它可以对几种不同类型的对象集合进行操作,并对它们采取适当的行动:
static void DoSomething(ICollection<TypeA> things)
{
// Do something with TypeA elements
}
static void DoSomething(ICollection<TypeB> things)
{
// Do something with TypeB elements
}
在我的代码的其他地方,有很多词典使用TypeA
或TypeB
作为键,并为其值使用各种类型。我最终收到了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来选择正确的重载。
我错过了一个更好的选择吗?
答案 0 :(得分:2)
您可以创建一个通用方法,接受字典值类型的类型参数:
doInBackground
答案 1 :(得分:0)
要做的最好的事情(如果你能控制TypeA
和TypeB
)就是让这两种类型都实现这样的界面:
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语句开始在整个地方突然出现。
如果您无法让TypeA
和TypeB
实现相同的界面,那么可能还有另一种方法可以重构SOLID principles。如果您对此问题的背景有任何其他问题,我相信SO社区很乐意回答一个单独的问题。