2016-03-24 134 views
2

我有一個類來處理傳入的空中消息並解析它們。根據命令的輸出,我需要處理一些UI修改,如高亮標籤,添加文本到文本框等,我用的是第一個選項是:C#更好的方式來處理多個if/else if語句

void IncomingMessageIfStatements(Message msg, Host host) 
     { 
      byte resp; 
      if (ParseMessageOptionOne(msg, out resp)) 
      { 
       // Do some windows form stuff 
      }  

      else if (ParseMessageOptionTwo(msg, out resp)) 
      { 
       // Do some windows form stuff 
      } 

      else if (ParseMessageOptionThree(msg, out resp)) 
      { 
       // Do some windows form stuff 
      } 
     } 

     private bool ParseMessageOptionOne(Message msg, out byte resp) 
     { 
      throw new NotImplementedException(); 
     } 
     private bool ParseMessageOptionTwo(Message msg, out byte resp) 
     { 
      throw new NotImplementedException(); 
     } 
     private bool ParseMessageOptionThree(Message msg, out byte resp) 
     { 
      throw new NotImplementedException(); 
     } 

這工作,但我將有更多的else if聲明,它可能會變得醜陋。接下來的方法是:

void IncomingMessageSwitchStatements(Message msg, Host host) 
     { 
      byte resp = 0; 
      byte someByte = 0; 
      bool output = false; 
      switch (someByte) 
      { 
       case 1: 
        output = ParseMessageOptionOne(msg, out resp); 
        break; 
       case 2: 
        output = ParseMessageOptionTwo(msg, out resp); 
        break; 
       case 3: 
        output = ParseMessageOptionThree(msg, out resp); 
        break; 
       default: 
        //handle exception here 
        break; 
      } 

      if (output && resp == 0x01) 
      { 
       UpdateUiFromHere(); 
      } 
     } 

     private void UpdateUiFromHere() 
     { 
      // handle UI updates here 
     } 

這看起來更清潔,並按預期工作。但後來我開始尋找Dictionary<byte, Func<bool>>,並認爲這可能是一種更好的方法來解決處理多個條件傳入(可能20)。

對於最佳做法,我有什麼建議嗎?

+0

的'之開關版本將始終execure默認分支......你說按預期工作? –

+2

似乎「if else」塊在邏輯上與「switch case」塊不同。ParseMessageOptionX返回bool,someByte來自哪裏? –

+0

交換機比if/else if/else更好。但是,如果有大量條件,則查找表(字典)會使您的代碼更加簡潔。 – RJM

回答

3

既然你想要做的是「基於索引號相同的簽名調用方法」,你可以使用delegate,並在Dictionary列出它們(或在List如果指數從0開始),讓您的意圖明確。

public delegate bool ParseMessage(Message msg, out byte resp); 

,然後使用Dictionary列出它:使用List

List<ParseMessage> parser = new List<ParseMessage>(){ 
    new ParseMessage(ParseMessageOptionOne), 
    new ParseMessage(ParseMessageOptionTwo), 
    new ParseMessage(ParseMessageOptionThree) 
}; 

Dictionary<byte, ParseMessage> parser = new Dictionary<byte, ParseMessage>(){ 
    {1, new ParseMessage(ParseMessageOptionOne)}, 
    {2, new ParseMessage(ParseMessageOptionTwo)}, 
    {3, new ParseMessage(ParseMessageOptionThree)} 
}; 

或並調用它是這樣的:

bool result = parser[resp](msg, out resp); //dictionary 
bool result = parser[resp-1](msg, out resp); //list 
+0

這完美解決。謝謝! –

0

我會動議解析到裏面的消息類本身。

Options option = msg.GetOption(); 

我還要做一個枚舉所有的選項:

public enum Options { 
    One, 
    Two, 
    None 
} 

然後再編寫代碼,以利用該但是你需要......

if (option == Options.One) 
// or 
switch(option) 
// etc. 

難建議更多,因爲我不知道什麼UpdateUiFromHere()做什麼,因爲它不需要parms ...但這應該是一些好的思考。

+0

這些可以是編寫自我記錄代碼的好建議,但不能解決OP的問題。 –

+0

@JonathanWood,OP的問題幾乎足以要求改寫或關閉過於寬泛:「對於我所應該採取的最佳做法提供什麼建議?我的回答更多的是使用'encapsulation',所以Message類包含了所有的邏輯,這將是一個「最佳實踐」。在某些問題上很難決定爲問題X做出回答,或者有助於解決問題Y(有時可能不是由OP直接在X中詢問)。 –

0

您可以也改變ParseMessageOptionOne的方法簽名,ParseMessageOptionTwo,ParseMessageOptionThree返回封裝輸出,響應並使用Func鍵內置委託儲存方法的響應對象:

public struct ParseResponse 
{ 
    public bool output; 
    public byte response; 
} 

class ParseOptions 
{ 
    Func<Message, ParseResponse>[] options = null; 

    public ParseOptions() 
    { 
     options = new Func<Message, ParseResponse>[]{ 
      ParseMessageOptionOne, 
      ParseMessageOptionTwo, 
      ParseMessageOptionThree 
     }; 
    } 

    public void IncomingMessageSwitchStatements(Message msg, Host host) 
    {    
     byte someByte = 2; 

     var response = options[someByte](msg); 

     if (response.output && response.response == 0x01) 
     { 
      //UpdateUiFromHere(); 
     } 
    } 

    private ParseResponse ParseMessageOptionThree(Message msg) 
    { 
     return new ParseResponse { output = true }; 
    } 

} 
0

另一種方法是使用LINQ循環遍歷委託方法列表,並在找到條件後儘快進行短程循環。

private delegate bool ParseMessageWrapper(Message msg, out byte resp); 

void IncomingMessageSwitchStatements(Message msg, Host host) 
{ 
    byte resp = 0; 
    bool output = false; 

    var parseMethods = new List<ParseMessageWrapper>() 
    { 
     new ParseMessageWrapper(ParseMessageOptionOne), 
     new ParseMessageWrapper(ParseMessageOptionTwo), 
     new ParseMessageWrapper(ParseMessageOptionThree) 
    }; 

    output = parseMethods.Any(func => func.Invoke(msg, out resp)); 

    if (output && resp == 0x01) 
    { 
     UpdateUiFromHere(); 
    } 
}