2011-04-07 2 views
0

У меня есть такой код, чтобы сделать его лучше (modbus_master.SetValue ("x1", Convert.ToInt32 (resipeDosings [i] .Massa) * 10, 1); - отправка данных в контроллер)Как упростить выбор (если)

public class RecipeDosings 
{ 
    public string Product { get; set; } 
    public string Persent { get; set; } 
    public string Massa { get; set; } 
    public string Bunker { get; set; } 

    public RecipeDosings(string product, string persent, string massa, string bunker) 
    { 
     this.Product = product; 
     this.Persent = persent; 
     this.Massa = massa; 
     this.Bunker = bunker; 
    } 
    } 

public List<RecipeDosings> resipeDosings = new List<RecipeDosings>(); 

     for (int i = 0; i < resipeDosings.Count; i++) 
     { 
      if (resipeDosings[i].Bunker == "Bunker 1") 
      { 
       modbus_master.SetValue("x1", Convert.ToInt32(resipeDosings[i].Massa) * 10, 1);  
      } 
      if (resipeDosings[i].Bunker == "Bunker 2") 
      { 
       modbus_master.SetValue("x1", Convert.ToInt32(resipeDosings[i].Massa) * 10, 1); 
      } 
      if (resipeDosings[i].Bunker == "Bunker 3") 
      { 
       modbus_master.SetValue("x1", Convert.ToInt32(resipeDosings[i].Massa) * 10, 1); 
      } 
      if (resipeDosings[i].Bunker == "Bunker 4") 
      { 
       modbus_master.SetValue("x1", Convert.ToInt32(resipeDosings[i].Massa) * 10, 1); 
      } 
      if (resipeDosings[i].Bunker == "Bunker 5") 
      { 
       modbus_master.SetValue("x1", Convert.ToInt32(resipeDosings[i].Massa) * 10, 1); 
      } 
      if (resipeDosings[i].Bunker == "Bunker 6") 
      { 
       modbus_master.SetValue("x1", Convert.ToInt32(resipeDosings[i].Massa) * 10, 1); 
      } 
      if (resipeDosings[i].Bunker == "Bunker 7") 
      { 
       modbus_master.SetValue("x1", Convert.ToInt32(resipeDosings[i].Massa) * 10, 1); 
      } 
      if (resipeDosings[i].Bunker == "Bunker 8") 
      { 
       modbus_master.SetValue("x1", Convert.ToInt32(resipeDosings[i].Massa) * 10, 1); 
      } 
      if (resipeDosings[i].Bunker == "Bunker 9") 
      { 
       modbus_master.SetValue("x1", Convert.ToInt32(resipeDosings[i].Massa) * 10, 1); 
      } 
     } 
+0

Есть много повторений. Есть ли лучший способ справиться с этим без кодирования «числа» в названии (или что-то еще)? –

ответ

7

Переключить оператор удаляет все if заявления -

switch (resipeDosings[i].Bunker) 
{ 
case "Bunker 1": 
    // code here 
    break; 
case "Bunker 2": 
    // code here 
    break; 

    // repeat case statements... 

default: 
    // this is the final 'else' code - if nothing matches 
} 

Однако две вещи очевидны:

  • Y ou're выполнение одного и того же кода независимо от
  • Вероятно, вы должны сохранить переменные (что-то, что может быть разным для каждого Бункер) в таблице поиска или таблице базы данных, поэтому вам не нужно изменять программу каждый раз, когда вы получить новый Bunker или хотите изменить значение

Самый простой способ построения LUT - использовать Dictionary<>.

Dictionary<string, int> bunkerLut = new Dictionary<string, int>(); 

bunkerLut["Bunker 1"] = 10; 
bunkerLut["Bunker 2"] = 11; 
bunkerLut["Bunker 3"] = 12; 

// and so on... I'm assuming there should be a value that's different for each bunker? I'm also assuming it's an int 

Тогда вы можете посмотреть, что-то вроде этого (предполагая, что 10 является значением, которое изменяется):

int result = bunkerLut[resipeDosings[i].Bunker]; 
modbus_master.SetValue("x1", Convert.ToInt32(resipeDosings[i].Massa) * result, 1); 

Другие варианты хранения значений в файле конфигурации или базы данных.

+0

, но поскольку код не становится меньше – emirate

+0

Все утверждения читаются одинаково, поэтому, если вы хотите намного меньше, используйте 'modbus_master.SetValue («x1», Convert.ToInt32 (resipeDosings [i] .Massa) * 10, 1); '' без утверждений 'if'. Если вам нужны разные значения, я обновляю свой ответ сейчас, ... –

+0

@emirate - вы не можете уменьшить размер кода, превышающий минимальное значение, необходимое для выполнения задачи. –

1

Так, кажется, нет никакой разницы в том, что делается для различных значений, вы можете просто проверить, что это один из значений для проверки наличия и выполнять действия, если это так:

var valuesToCheck = new[] { 
    "Bunker 1", 
    "Bunker 2", 
    "Bunker 3", 
    "Bunker 4", 
    "Bunker 5", 
    "Bunker 6", 
    "Bunker 7", 
    "Bunker 8", 
    "Bunker 9"}; 

for (int i = 0; i < resipeDosings.Count; i++) 
{     
    if (valuesToCheck.Contains(resipeDosings[i].Bunker) 
    { 
     modbus_master.SetValue("x1", Convert.ToInt32(resipeDosings[i].Massa) * 10, 1);  
    }  
} 
0

еще одно:
Если вы используете if в том, что вы делаете, то есть с чеками, из которых только один может быть правдой в то время, используйте else if, поэтому он не будет оценивать выражения, которые, как известно, ложь:

if(cond1) 
{ 
    // do stuff 
} 
else if(cond2) 
{ 
    // do stuff 
} 
else if(cond3) 
{ 
    // do stuff 
} 

Но делайте это только, если нет лучшей альтернативы, например, switch или что-то еще ...

1

Я мог бы что-то игнорировать, но нет никакой разницы в каждом случае бункера.

for (int i = 0; i < resipeDosings.Count; i++) 
    modbus_master.SetValue("x1", Convert.ToInt32(resipeDosings[i].Massa) * 10, 1); 

Это будет делать то же самое.

2

Эмм, до тех пор, пока не будет никакой разницы в том, как вы их лечить:

public List<RecipeDosings> resipeDosings = new List<RecipeDosings>(); 

for (int i = 0; i < resipeDosings.Count; i++) 
{ 
    if (resipeDosings[i].Bunker.StartsWith("Bunker ")) 
    { 
     modbus_master.SetValue("x1", Convert.ToInt32(resipeDosings[i].Massa) * 10, 1);  
    } 
} 
+1

Стоит добавить, что это не эквивалентно, он также примет «Бункер», «Бункер A», «Бункер (недействительный)», или что у вас есть - –

+1

Да, вы абсолютно правы. С другой стороны, у нас нет требования знать, что должно быть в матче. Поэтому StartsWith() следует заменить каким-то соглашением, которое соответствует требованиям. –

+0

На самом деле, потому что есть только «' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ' исключения, а все остальное, начиная с «Бункер», следует игнорировать вообще. Odd :) –

3

Вы можете сделать следующее:

for (int i = 0; i < resipeDosings.Count; i++) 
{ 
    switch(resipeDosings[i].Bunker) 
    { 
     case "Bunker 1": 
     case "Bunker 2": 
     case "Bunker 3": 
     case "Bunker 4": 
     case "Bunker 5": 
     case "Bunker 6": 
     case "Bunker 7": 
     case "Bunker 8": 
     case "Bunker 9": 
     case "Bunker 10": 
      modbus_master.SetValue("x1", Convert.ToInt32(resipeDosings[i].Massa) * 10, 1); 
      break; 
     default: 
      break; 
    } 
} 
+0

Нет, вы не можете. C# не разрешает провал в случаях. – BoltClock

+3

@BoltClock - но это позволяет вам складывать ярлыки кейсов, так что это совершенно верно (да, вы можете) –

+0

@Kieren Johnstone: О, мой плохой тогда :) – BoltClock

0

Я есть словарь строки/FUNC, что-то вроде этого;

class EmirateRefactored 
{ 
    public List<RecipeDosings> resipeDosings = new List<RecipeDosings>(); 
    private Dictionary<string, Func<RecipeDosings, int>> m_objActionMapping; 

    public EmirateRefactored() 
    { 
     m_objActionMapping = new Dictionary<string, Func<RecipeDosings, int>>(); 
     m_objActionMapping.Add("Bunker 1", bunker1); 
     m_objActionMapping.Add("Bunker 2", bunker2); 
     //etc 
    } 

    public void Process(ModBusMaster modbus_master) 
    { 
     foreach (RecipeDosings rd in resipeDosings) 
     { 
      if (m_objActionMapping.ContainsKey(rd.Bunker)) 
      { 
       int result = m_objActionMapping[rd.Bunker].Invoke(rd); 
       modbus_master.SetValue(result); 
      } 
      else 
       throw new ApplicationException("Couldn't parse bunker!"); 
     } 
    } 

    /// <summary> 
    /// I have no idea what this is as it's not included in the sample code! 
    /// </summary> 
    public class ModBusMaster 
    { 
     public void SetValue(int i_intInput) { } 
    } 

    /// <summary> 
    /// Some code relevant to "bunker 1" 
    /// </summary> 
    private int bunker1(RecipeDosings i_objRecipe) 
    { 
     return Convert.ToInt32(i_objRecipe.Massa) * 10; 
    } 
    /// <summary> 
    /// Some code relevant to "bunker 2" 
    /// </summary> 
    private int bunker2(RecipeDosings i_objRecipe) 
    { 
     //bunker2 code 
     return Convert.ToInt32(i_objRecipe.Massa) * 10; 
    } 
} 

Я делаю несколько предположений, и понятия не имеют, что фактические требования без дополнительной выборки кода/например, спички, и т.д., и т.д.

Редактировать: прочитав несколько комментариев к другим ответам, вы можете легко изменить это на словарь Regex/func. И из метода процесса; если свойство «Бункер» соответствует регулярному выражению Invoke func.

Смежные вопросы