2016-03-24 5 views
2

Ich habe eine Klasse, die eingehende Over-the-Air-Nachrichten verarbeitet und analysiert. In Abhängigkeit von der Ausgabe des Befehls, muss ich einige UI Änderungen umgehen wie Etiketten hervorheben, das Hinzufügen von Text zu Textfelder usw. Die erste Option war ich mit ist:C# Bessere Möglichkeit, mehrere if/else if-Anweisungen zu behandeln

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(); 
     } 

Dies funktioniert, aber ich werde mehr else if Aussagen und es könnte hässlich werden. Der nächste Weg, den ich sah, ist:

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 
     } 

Dies sieht viel sauberer und funktioniert wie vorgesehen. Aber dann fing ich an, Dictionary<byte, Func<bool>> zu betrachten und dachte, dass das vielleicht ein besserer Ansatz zur Lösung der Behandlung von mehreren eingehenden Bedingungen (möglicherweise 20) war.

Irgendwelche Vorschläge zu den Best Practice sollte ich gehen, gegeben, was benötigt wird?

+0

Die 'Schalter' Version wird immer execure Standardzweig ... Sie sagen, es ist wie beabsichtigt funktioniert? –

+2

Scheint, dass der Block "if else" logisch nicht der gleiche wie der "switch case" ist.ParseMessageOptionX gibt bool zurück, woher kommt someByte? –

+0

Switch ist besser als wenn/sonst wenn/sonst. Wenn es jedoch eine große Anzahl von Bedingungen gibt, würde eine Nachschlagetabelle (Wörterbuch) Ihren Code prägnanter machen. – RJM

Antwort

3

Da das, was Sie tun möchten, ist es, „Call-Methode mit der gleichen Signatur basierend auf Indexnummer“, Sie delegate verwenden könnten und in der Liste in einem Dictionary (oder in einem List, wenn der Index von 0 beginnt) Sie zu machen Absicht klar.

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

Und dann geben Sie es Dictionary mit:

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

oder List

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

verwenden und es so nennen:

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

Das hat perfekt funktioniert. Vielen Dank! –

0

ich das Parsen bewegen würde zu innerhalb der Nachrichtenklasse selbst.

Options option = msg.GetOption(); 

Ich würde auch eine ENUM für alle Optionen machen:

public enum Options { 
    One, 
    Two, 
    None 
} 

Dann Code schreiben Verwendung, das zu machen, aber Sie brauchen ...

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

Hard to Ich empfehle mehr, da ich nicht sagen kann, was UpdateUiFromHere() tut, da es keine Parms braucht ... aber das sollte ein guter Grund zum Nachdenken sein.

+0

Das können gute Empfehlungen sein, um selbstdokumentierenden Code zu schreiben, aber nicht die Frage des OP. –

+0

@ JonathanWood, die OP-Frage ist fast genug, um umzuschreiben oder zu schließen, als zu breit: "Irgendwelche Vorschläge für die beste Praxis, die ich gehen sollte, gegeben, was benötigt wird?" Meine Antwort lautete eher "Kapselung", so dass die Message-Klasse die gesamte Logik enthält, was eine "Best Practice" wäre. Bei einigen Fragen fällt es schwer, sich für die Frage X zu entscheiden oder zu helfen, das Problem Y zu lösen (das vielleicht nicht direkt von den OPs in X angefordert wird). –

0

Sie können auch die Methodensignatur von ParseMessageOptionOne ändern, ParseMessageOptionTwo, ParseMessageOptionThree eine Antwort Objekt zurückzugeben, die Ausgabe, Antwort kapselt und verwenden Func Einbau-Delegatmethoden zu speichern:

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

Eine weitere Alternative wäre, Verwenden von LINQ zum Durchlaufen einer Liste von Delegate-Methoden und Kurzschließen, sobald eine true Bedingung gefunden wird.

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(); 
    } 
}