C# 重构大型if-else代码

C# 重构大型if-else代码,c#,.net,refactoring,C#,.net,Refactoring,我有很长的if-else代码 if (errorNumbers.Length == 6) { if (errorNumbers.Substring(0,4).Equals("1101") || errorNumbers.Substring(0,4).Equals("2121")) { retStr = "AutoRepickAfterPickError"; } else if (errorNumbe

我有很长的if-else代码

 if (errorNumbers.Length == 6)
      {
        if (errorNumbers.Substring(0,4).Equals("1101") || errorNumbers.Substring(0,4).Equals("2121"))
        {
          retStr = "AutoRepickAfterPickError";
        }
        else if (errorNumbers.Substring(0, 4).Equals("1301") || errorNumbers.Substring(0, 4).Equals("2321"))
        {
          retStr = "AutoRepickAfterLAlignError";
        }
        else if (errorNumbers.Substring(0, 4).Equals("1401") || errorNumbers.Substring(0, 4).Equals("2221"))
        {
          retStr = "AutoRepickAfterCAlignError";
        }
        else if (errorNumbers.Substring(0, 4).Equals("1501") || errorNumbers.Substring(0, 4).Equals("2041"))
        {
          retStr = "AutoRepicksAfterManualRecovery";
        }
等等

我怎么能把它改写成更好的东西。 尝试在这里学习一些新的东西,我现在在.NET2.0中。
谢谢你的帮助。

这应该很简单

if (errorNumbers.Length == 6)
{
    string errNo = errorNumbers.Substring(0, 4);

    switch (errNo)
    {
        case "1101":
        case "2121":
            retStr = "AutoRepickAfterPickError";
            break;
        case "1301":
        case "2321":
            retStr = "AutoRepickAfterLAlignError";
            break;
        case "1401":
        case "2221":
            retStr = "AutoRepickAfterCAlignError";
            break;
        case "1501":
        case "2041":
            retStr = "AutoRepicksAfterManualRecovery";
            break;
    }
}
还请注意,与Java不同,在C语言中,您可以将字符串与
=
进行比较


“123”==“456”
的作用与
“123”的作用相同。等于(“456”)

首先,在长if/else之前将
errorNumber.Substring(0,4)
存储在局部变量中


然后,您可以使用映射/字典将整个if/else从预期的错误号消除到相应的返回字符串。

我将错误代码映射到字典中,如下所示:

string errorCode = errorNumbers.Substring(0, 4);
Dictionary<string, string> map = new Dictionary<string,string>();
map.Add("1501", "AutoRepicksAfterManualRecovery");
map.Add("2041", "AutoRepicksAfterManualRecovery");
map.Add("1401", "AutoRepickAfterCAlignError");
map.Add("2221", "AutoRepickAfterCAlignError");
map.Add("1301", "AutoRepickAfterPickError");
map.Add("2121", "AutoRepickAfterPickError");
// etc

if(!map.ContainsKey(errorCode))
 throw new Exception("Invalid error code");

return map[errorCode];
stringerrorcode=errorNumbers.Substring(0,4);
字典映射=新字典();
地图添加(“1501”,“自动恢复”);
地图添加(“2041”,“自动恢复”);
地图添加(“1401”,“自动校准错误”);
地图添加(“2221”,“自动校准错误”);
map.Add(“1301”,“自动检索错误”);
添加(“2121”,“自动检索错误”);
//等
如果(!map.ContainsKey(错误代码))
抛出新异常(“无效错误代码”);
返回映射[错误代码];

选择案例怎么样D

errorNumber = errorNumbers.Substring(0,4)
Select Case errorNumber 
   Case 1101,2121
      retStr = "AutoRepickAfterPickError";
   Case 1301,2321
      retStr = "AutoRepickAfterLAlignError";
   ...
End Select
首先。将
errorNumbers.子字符串(0,4)
的结果分配给局部变量:

string subNumbers = errorNumbers.SubString(0, 4);
if (subNumbers == "1401") // ...
支持特定价值案例(非范围):

可以将switch语句与字符串一起使用:

switch(subNumbers)
{
    case "1401":
    case "2221":
      retStr = "AutoRepickAfterCAlignError";
      break;
    case "1501":
    case "2041":
      retStr = "AutoRepicksAfterManualRecovery";
      break;
    // etc
}
switch语句的另一种替代方法是创建字典:

var selections = new Dictionary<string, string>()
{
    { "1401", "AutoRepickAfterCAlignError" },
    { "2221", "AutoRepickAfterCAlignError" },
    { "1501", "AutoRepicksAfterManualRecovery" },
    { "2041", "AutoRepicksAfterManualRecovery" },
    // etc
};

if (selections.ContainsKey(subNumbers))
    retStr = selections[subNumbers];
var selections=newdictionary()
{
{“1401”,“自动校准错误”},
{“2221”,“自动校准错误”},
{“1501”,“自动恢复”},
{“2041”,“自动恢复”},
//等
};
if(选择项.容器(子编号))
retStr=选择[子编号];
范围:

如果需要支持范围,则基本上必须使用
If
/
else
块。还有其他选项,但如果代码中只有这么多的
if
/
else
块,则这些选项往往过于复杂。

您可以尝试以下方法:

if (errorNumbers.Length == 6)
{

    //Makes it easier to change error codes, as theyre all in one place
    string[] AutoRepickAfterPickError = { "1101", "2121"};
    string[] AutoRepickAfterLAlignError = { "1301", "2321"};
    string[] AutoRepickAfterCAlignError = { "1401", "2221"};
    string[] AutoRepicksAfterManualRecovery = { "1501", "2041"};
    string subString = errorNumbers.Substring(0,4);

        if (AutoRepickAfterPickError.Contains(subString));
        {
          retStr = "AutoRepickAfterPickError";
        }
        else if (AutoRepickAfterLAlignError.Contains(subString))
        {
          retStr = "AutoRepickAfterLAlignError";
        }
        else if (AutoRepickAfterCAlignError.Contains(subString))
        {
          retStr = "AutoRepickAfterCAlignError";
        }
        else if (AutoRepicksAfterManualRecovery.Contains(subString))
        {
          retStr = "AutoRepicksAfterManualRecovery";
        }
}

您应该使用errorCode和errorMessage之间的引用来初始化字典

Dictionary<int, string> errorsCache = new Dictionary<int, string>()
{
  {1101,"AutoRepickAfterPickError"},
  {2121,"AutoRepickAfterPickError"},
  {1401,"AutoRepickAfterCAlignError"},
  ...
}

首先,干的原则-不要重复你自己()。将
errorNumbers.Substring(0,4)
的结果分配给一个局部变量。您“可以”使用策略模式,但在大多数情况下,这是一个完全的过度使用,有时很难维护。这是一个C#而不是VB.Net问题。最好是删除答案大IfElse/SwitchCase保留在此处接受的,它实际上更冗长,可能更快。我只是不喜欢switch,因为它添加了额外的代码。它没有什么“错误”,但是字典,最好是这样的静态字典,比switch语句更容易维护。是的,我也会使用它,这在我的示例中不是很明显,因此接受的答案可能更详细一些。dictionary和switch的性能可能非常相似,因为带字符串的switch可能会在后台使用哈希表。但是,此示例中的两个查找而不是一个查找(例如TryGetValue)会使查找速度稍慢。它还应该是一个缓存的静态字典,如@Yaur所说。如果性能对这段代码很重要……事实上,我利用ContainsKey使示例更直观。然后,对于列表中的6-12个条目,问题是这是否有什么区别,但坚持练习总是好的:)
public string GetErrorDescription(string errorNumbers)
{
  string retStr;
  if (errorNumbers.Length == 6)
  {
    int errorCode;  
    if(int.TryParse(errorNumbers.Substring(0,4), out errorCode))
    {
      errorsCache.TryGetValue(errorCode, out retStr);
    }
  }

  return retString;
  // or you can return empty string instead of null
  return retString ?? "";
}