4

有没有可能用一些更短、更易读的代码来编写下一个开关?

switch (SomeValue)
{
  case "001": return DoMethod1(); break;
  case "002": return DoMethod2(); break;
  //etc..
}

我在想某种方式

Dictionary<string, Func<int>> MethodsByValue = new Dictionary<string, Func<int>>()
{
    { "001", DoMethod1 },
    { "002", DoMethod2 },
}

并通过这样做来调用它

return MethodsByValue[SomeValue]();

但这甚至可能吗?还是我在想办法开箱即用。我找不到任何这样的东西,但话又说回来,如果可能的话,我不知道这个关键字。

编辑:回答 Lasse V. Karlsen 的要求:

这就是我的项目中的代码。在某些地方更改名称会导致原始名称无关紧要,因为它是我的母语。

public string GetRecord420(Dictionary<DataClass, object> dictionaryName)
{
  // some code here
}

public string GetRecord421(Dictionary<DataClass, object> dictionaryName)
{
  // some code here
}

//(Temperary) solution with the switch statement in a wrapper:
public string GetRecordByString(string s, Dictionary<DataClass, object> dictionaryName)
{
  switch (s)
  {
    case "320": return GetRecord420(dictionaryName);
    case "321": return GetRecord421(dictionaryName);
    default: return String.Empty;
  }
}

//How I hoped it could be, with a mapping dictionary.
public Dictionary<string, Func<string, Dictionary<DataClass, object>>> MethodByString = 
   new Dictionary<string, Func<string, Dictionary<DataClass, object>>>()
{
  { "320", GetRecord420 },
  { "321", GetRecord421 },
}

DataClass是一个Entity类,里面存储了一些列数据(列名、列类型等)。

我尝试了字典部分,但它给了我错误:无法从方法组转换为 System.Func<...>。

更改为 () => GetRecord420 给我错误:无法将 lambda 转换为委托类型 System.Func<...> 因为块中的某些返回类型不能隐式转换为委托返回类型。

4

4 回答 4

1

您的方法定义一定有错误,

class Program
{
    static void Main()
    {
       var methods = new Dictionary<string, Func<int>>
           {
               { "001", DoMethod1 }
           };
    }

    static int DoMethod1()
    {
        return 1;
    }
}

是完全有效的语法。

但是,这并不比switch1 个令人信服和 1 个主观原因更好。

如果您要与常量或文字进行比较,那么您应该使用 switch。这使编译器无需额外分析即可执行编译时优化。

更主观的是,字典/查找方法并不短,我发现它更难阅读。但是,在您的比较项在运行时发生变化的情况下,它会很有用。

如果您想避免将switch因子重写为函数。说,

Func<int> MethodsByValue(string value)
{
    switch(value)
    {
        case "001":
            return DoMethod1;

        default:
            return DoMethod2;
    }
}

无论哪种方式,

与其使用一些任意字符串来枚举您的方法,不如使用enum? 然后,您将获得额外的性能和可读性优势。

于 2013-06-17T10:10:42.897 回答
0

我为此使用了映射扩展。这样 yoy 可以使用以下语法:

    return SomeValue
    .Map("001", DoMethod1)
    .Map("002", DoMethod2)
     //etc

这也可以做到这一点:

    return SomeValue
    .Map(1, DoMethod1)
    .Map(2, DoMethod2)
    .Map(x => x < 0, DoMethod3)
    .Map(x => x > 5  && x < 10, DoMethod4)
    .Else(4); // a simple value of a method
于 2013-07-21T19:28:35.483 回答
0

一般来说,switch 的一个很好的替代方案是使用State Design Pattern其他很好的替代方案是Strategy Pattern。它将使您的代码更具可扩展性并且是更加面向对象的方法。

于 2013-06-17T10:28:02.833 回答
0

您可以通过删除多余break的 s 来缩短您所拥有的内容,如果碰巧两种情况应该调用相同的方法,那么您可能会失败:

switch (SomeValue) {
  case "001": return DoMethod1();
  case "002": return DoMethod2();
  case "003": 
  case "004": return DoMethod34();
  //etc..
}

至于你的伪建议,以及另一个提倡它的答案,我看不出这是多么简短或更简洁。但是,在使用中是可以减少代码并清晰的,例如,简单地说:

Func<int> GetMethod(string key) {
  return MethodsByValue[key];
}
Func<int> method = GetMethod("001");
method();
于 2013-06-17T10:23:33.113 回答