2016-03-24 3 views
2

У меня есть класс, который обрабатывает входящие сообщения в эфир и анализирует их. В зависимости от вывода команды, мне нужно обрабатывать некоторые модификации пользовательского интерфейса, такие как выделение ярлыков, добавление текста в текстовых и т.д. Первый вариант я использую это: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

Параметр 'switch' версия будет всегда execure по умолчанию филиал ... Вы говорите, что он работает как задумано? –

+2

Кажется, что блок «if else» логически не совпадает с «случаем коммутатора».ParseMessageOptionX возвращает bool, откуда приходит someByte? –

+0

переключатель лучше, чем if/else if/else. Однако, если существует большое количество условий, тогда таблица поиска (словарь) сделает ваш код более кратким. – RJM

ответ

3

Так что вы хотите сделать, это «вызов метода с той же подписью, основанной на индексный номер», вы могли бы использовать delegate и перечислить их в Dictionary (или в List, если индекс начинается с 0), чтобы сделать ваш намерение прозрачный.

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

А затем перечислить его с помощью Dictionary:

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

или с помощью List

List<ParseMessage> parser = new List<ParseMessage>(){ 
    new ParseMessage(ParseMessageOptionOne), 
    new ParseMessage(ParseMessageOptionTwo), 
    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(), так как он не принимает парм ... но это должно быть хорошей пищей для размышлений.

+0

Это могут быть хорошие рекомендации для написания самодокументирующего кода, но не затрагивает вопрос OP. –

+0

@JonathanWood, вопрос OPs почти достаточно, чтобы попросить переделать или закрыть слишком широко: «Любые предложения по лучшей практике, на которые я должен пойти, учитывая, что нужно?» Мой ответ был более похож на использование 'encapsulation', поэтому класс Message содержит всю логику, которая была бы« лучшей практикой ». На некоторые вопросы сложно решить ответить на вопрос X или помочь решить проблему Y (которая иногда не задается непосредственно в 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 для циклического перебора списка методов делегатов и короткого замыкания, как только будет найдено условие true.

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(); 
    } 
} 
Смежные вопросы