【问题标题】:Avoid hardcoding in switch statement避免在 switch 语句中进行硬编码
【发布时间】:2011-09-26 10:51:47
【问题描述】:

我有一个具有两个属性的对象:TextType

为了避免对类型进行硬编码,我将它们放在数据库中,以便将来添加。目前类型为URL, Username and ID

但是,我现在想运行一个 Utility 方法来清理对象的 Text 字段,基于该对象是哪个 Type(例如,如果它是一个 URL,则添加“http://”)。

有没有办法在 Utilities 类中执行此操作,而无需在 switch 语句/if else 块中硬编码类型。

switch (type)
{
    case 1:
        TidyUrl();
    case 2:
        TidyUsername();
    case 3:
        TidyID();
    default:
        break;
}

在本例中,我从数据库(“类型”表)中硬编码 ID,这绝不是一件好事!

有没有更好的方法来做到这一点?

【问题讨论】:

  • 无论我在数据库中使用接口和工厂、枚举器还是方法名称,似乎都无法绕过 if/else 逻辑,这将需要在某处说出哪个是哪个,这就是我找不到避免硬编码的方法。

标签: c# if-statement switch-statement hard-coding


【解决方案1】:

您可以使用枚举来帮助提高可读性。

enum MyTypes
{
 URL = 1,
 UserName = 2,
 Id = 3,
}

switch (myType)
{
    case MyTypes.URL:
        TidyUrl();
    case MyTypes.UserName:
        TidyUsername();
    case MyTypes.Id:
        TidyID();
    default:
        break;
}

这个枚举需要与数据库保持协调。

【讨论】:

  • 是的,我过去做过这个,但它似乎只是把同样的问题(保持 ids 同步)放在不同的地方。
  • @finoutlook - 但至少它是清楚那个地方在哪里。根据我的经验,您必须在代码库中某处有一个映射。
  • 是的,我同意它更清晰(并且可以将其他映射组合在一起,例如在 Enumerators 类中)并且比通过代码传播更好。
【解决方案2】:

一种方法是使用多态性。您的每个“类型”都有单独的类,它们会使用Tidy 之类的方法实现一个通用接口(或具有一个通用基类),每个接口都有自己的逻辑。

【讨论】:

  • 还有一个工厂方法,它将查找数据库中编码的类型并创建该类型的新对象。可能使用switch 语句;)
  • @Oded - 确切地说,无论选择什么,我都必须将我的代码直接链接到数据库中的内容
  • 是的,这是真的;但是这种技术避免了那些 switch 语句的扩散。你只需要一个。或者 none,如果您更喜欢使用反射...
【解决方案3】:

传统上,这是使用通用接口处理的,并动态构建具体实现来完成实际工作。

例如:

public interface ITidy
{
   string Tidy(string input);
}

然后是实现

public class UrlTidy : ITidy
{
    public string Tidy(string input)
    {
        // do whatever you need to the url
    }
}

其他类型的整理等等。现在您需要一种从您正在查看的类型实例化正确的具体类(UrlTidyIdTidy 等)的方法。一种方法可能是将类名与类型放在数据库中,并使用反射来实例化ITidy 的正确实现。另一种方法是拥有一个Factory 类,它使用其他方法根据类型实例化正确的ITidy

【讨论】:

  • 将类或方法名放入数据库中就像硬编码相反。不过这可能更可取。
  • @finoutlook - 不像硬编码。完全相反,允许您动态扩展类型(假设您发布了一个包含该类的新程序集)。它类似于一个插件系统,允许您在不释放整个软件的情况下扩展应用程序的功能。
  • 是的,我看到了它在数据库中的优势。使维护变得更加容易,而且您是对的,它可以动态更改。
【解决方案4】:

您可以使用enum Type,但它们的常量值必须在编译时确定。您可以在enum 中放置类不变性检查,以确保与数据库一致。

但是将它们放在数据库中如何使其可扩展?

【讨论】:

  • 我认为你的问题很好,为什么它可以扩展。方法数量有限,但数据库中的某些类型可能共享相同的方法,例如新的UrlWithQuerystring 类型可能使用相同的TidyUrl() 方法。
  • 如果您不想对数字进行硬编码,那么我上面概述的解决方案应该可以很好地工作。如果您可以为每种类型创建单独的类,将 typeid 和处理程序类放入数据库表中并初始化处理程序对象并在启动时将它们存储在注册表中,则可以加分。
【解决方案5】:

正如 Oded 所说,使用枚举:

public enum Types
{
    Type1 = 1,
    Type2 = 2,
    Type3 = 3
}

然后您可以将类型变量转换为枚举,将整数映射到数据库 ID:

switch ((Types)type)
{
    case Types.Type1:
        break;
    case Types.Type2:
        break;
    ...
}

希望有帮助

【讨论】:

    猜你喜欢
    • 2021-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-14
    相关资源
    最近更新 更多