避免在c#工厂方法中使用多个if语句

本文关键字:if 语句 工厂 方法 | 更新日期: 2023-09-27 18:05:41

我有C# application,在NoSQL database中存储数据。该应用程序有一个存储库类,它使用一系列对象将数据从NoSQL形式转换为c#模型使用的数据,反之亦然(本质上是ORM的一种形式)。这些对象实现一个converter接口,并且每个对象在一个特定的data type (string, bool, etc)上工作。在内部,它们使用反射来执行转换。这些对象的实例由返回给定类型对象的方法创建。当前的逻辑看起来像下面这样:

if(type == typeof(string)
    return new StringConverter(...);
if(type == typeof(int) || type == typeof(uint))
    return new IntegerConverter(...);
... // and so on

然而,所有这些if语句都困扰着我。我知道我可以做一些事情,比如创建一个字典来映射类型到创建方法,但我不确定这是否会导致更易读,易于维护/扩展的代码(?)。如果需要创建类型抽象,最好的方法是什么?欢迎提出任何建议。非常感谢。

避免在c#工厂方法中使用多个if语句

理想情况下,嵌套的if-statements是您想要避免的。我引用了微软的完整代码书。我们的想法是,当你设置了3个关卡时,维护代码的开发人员或你作为开发人员的注意力就会急剧减少。在您的情况下,如果您的逻辑必须硬编码,那么就没有办法避免使用if语句序列。然而,一个聪明的方法是遵循工厂设计模式。《四人帮》

您应该将if代码导出到一个工厂类。

正如您在这里看到的,工厂是一个GoF模式,它产生不同种类的物体。

在工厂类中,这个数量的int类型是可以的。

你应该只避免嵌套if语句,它们使你的代码不可读

考虑到可读性,您应该选择

switch(type.FullName){
  case(typeof(int).FullName) => //your logic
  ...
}

switch-case-Statement是比If-Else更可读的代码,而且速度更快。你可以在这里阅读更多信息:

对于少数项目,差异很小。如果你有很多东西,你一定要使用开关。

如果一个开关包含多于5个项目,则使用a来实现查找表或散列表。这意味着所有的项目都是相同的访问时间,与if:s列表相比,最后一项花费很多时间更多的时间到达,因为它必须评估每个先前的条件第一。

和其他人已经说过,外包你的switch-case到一个工厂类。

我相信您将类型映射到字典的想法将是您最好的选择,因为这实现了策略模式,并且本身非常具有表现力。

var converterStrategies = new Dictionary<Object, IConverter>();
converterStrategies.Add(typeOf(string), new StringConverter(...));

然后在传递引用类型时使用TryGetValue。

您可以考虑将此字典作为类的私有成员,并在包含类的初始化时填充它。

Gary McLean Hall在他的书《Adaptive Code via c#》中演示了这个模式,它在这种情况下给了我很大的帮助!