【问题标题】:C# iterate over switch's casesC# 遍历 switch 的 case
【发布时间】:2009-09-01 08:16:12
【问题描述】:

是否可以通过编程方式检索 switch 的所有情况?我不知道,也许是 IL 但不知道该怎么做......

事实上,我的全球问题如下:我得到了一个带有字符串作为属性名称的 siwtch 案例。方法很重要,不允许回归。我不希望重构破坏这一点,所以我想要一种方法来测试所有 case 字符串实际上是我的对象的真实属性。 (注意:默认值返回一些东西,所以我不能为重构的无效值抛出异常)。

【问题讨论】:

  • 只是好奇:您打算在构建过程中运行此检查吗?
  • 不,我想将它添加到类的静态构造器中或显式调用它,但我可以想象在构建过程中这样做。

标签: c# switch-statement il


【解决方案1】:

有一些方法可以避免在代码中直接使用属性名称作为字符串。我已经发布了一个代码 sn-p here

然后,不要使用 switch 语句,而是实现如下内容:

private IDictionary<string, Action> _actions;

public void RegisterAction(string propertyName, Action action)
{
    _actions.Add(propertyName, action);
}

public void DoSomething(string propertyName)
{
    _actions[propertyName]();
}

当您调用这两个方法时,请确保使用代码 sn-p 的 Member 类(请参阅链接),而不是直接使用属性名称。因此,您可以确保您的代码是可重构的,因为它不包含任何“魔术字符串”。

最好的问候

【讨论】:

  • 最后,按照建议使用链接帖子上显示的代码和字典,谢谢!
【解决方案2】:

在 IL 中,switch 语句编译成这样:

// ...
L_000c: ldloc.1 
L_000d: ldstr "case1"
L_0012: call bool [mscorlib]System.String::op_Equality(string, string)
L_0017: brtrue.s L_0035
L_0019: ldloc.1 
L_001a: ldstr "case2"
L_001f: call bool [mscorlib]System.String::op_Equality(string, string)
L_0024: brtrue.s L_0042
L_0026: ldloc.1 
L_0027: ldstr "case3"
L_002c: call bool [mscorlib]System.String::op_Equality(string, string)
L_0031: brtrue.s L_004f
// ...

编写可以在所有情况下正确分析此问题的代码将是相当多的工作。

我可以看到测试这一点的唯一方法是实际涵盖所有情况并确保您最终不会得到一个空的 PropertyInfo。如果您正在使用的代码非常重要并且不会失败,那么在任何情况下使用反射都可能非常危险。你能转向更安全的设计吗?

【讨论】:

  • 如果开关变大,C# 编译器将生成一个哈希表作为开关实现......确实不太友好 :)
  • 相反,如果开关不小,获取哈希表是小菜一碟——请参阅下面的答案。
  • 当然,我没想到会很容易做到。实际上代码可以抛出异常,我只是不希望它以无效的字符串作为属性。
【解决方案3】:

获取开关中的值并非易事...

如果您在开关中使用枚举而不是字符串,则可以使用Enum.GetValues 轻松获取枚举的值。

【讨论】:

    【解决方案4】:

    在 AWK 或 Perl 或其他任何工具中编写一个脚本来检查源代码本身,并在每次构建之前运行它。

    【讨论】:

      猜你喜欢
      • 2021-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-01
      • 2020-08-16
      • 2021-04-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多