2011-08-03 3 views
2

Hi,Проблема с удалением оператора "if"

Я пытаюсь найти способ, как улучшить этот код. Я хотел бы удалить инструкцию "if" из метода CreateAttributes. Основная идея этого метода, чтобы добавить атрибут в список, если этот атрибут удовлетворяет некоторые условия

internal class FildMap 
    { 
    public string ExactTargetFild { get; set; } 
    public string DbFild { get; set; }  
    public Type Type { get; set; } 
    } 

    internal static class FildMapProcessor 
    { 
    private static readonly List<FildMap> Map = new List<FildMap>(); 

    static FildMapProcessor() 
    { 
     if(Map.Count == 0) 
     { 
     Map.Add(new FildMap {ExactTargetFild = "Address 1", DbFild = "Address1", Type = typeof (string)}); 
     Map.Add(new FildMap { ExactTargetFild = "Date of birth", DbFild = "DateOfBirth", Type = typeof(DateTime) }); 
     Map.Add(new FildMap { ExactTargetFild = "Wine Beer", DbFild = "pref_WineBeerSpirits", Type = typeof(bool) }); 
     ......... 
     } 
    } 

    public static Attribute[] CreateAttributes(this DataRow row) 
    { 
     var attributes = new List<Attribute>(); 
     foreach (var item in Map) 
     { 
     if (item.Type == typeof(string)) 
     { 
      var value = row.Get<string>(item.DbFild); 
      if (value != null) 
      attributes.Add(new Attribute{Name = item.ExactTargetFild, Value = value}); 
     } 

     if (item.Type == typeof(DateTime)) 
     { 
      var value = row.Get<DateTime>(item.DbFild); 
      if (value != DateTime.MinValue) 
      attributes.Add(new Attribute { Name = item.ExactTargetFild, Value = value.ToString("dd/MM/yyyy") }); 
     } 

     if (item.Type == typeof(bool)) 
     { 
      if (row.Contains(item.DbFild)) 
      { 
      var value = row.Get<bool>(item.DbFild); 
      attributes.Add(new Attribute { Name = item.ExactTargetFild, Value = value.ToString() }); 
      } 
     } 
     } 

     return attributes.ToArray(); 
    } 
    } 

Спасибо,

ответ

6

Вы можете использовать полиморфизм здесь

internal abstract class FildMap 
    { 
    public string ExactTargetFild { get; set; } 
    public string DbFild { get; set; }  
    public abstract List<Attributes> GetAttributes(DataRow row); 
    } 

    internal class StringFildMap : FildMap 
    { 
    public override List<Attributes> GetAttributes(DataRow row) 
    { 
     //string specific stuff 
    } 
    } 

создавать другие классы для других типов

public static Attribute[] CreateAttributes(this DataRow row) 
{ 
    var attributes = new List<Attribute>(); 
    foreach (var item in Map) 
    { 
    attributes.AddRange(item.GetAttributes(row)); 
    } 

    return attributes.ToArray(); 
} 
+0

да, это хорошее решение. благодаря – ukraine

0

первого улучшение качества было бы использовать еще если. Это будет означать то же самое для примера, опубликованного, но немного лучше.

Для такого рода вещи я предпочитаю использовать если

например

if(){ 
} 
else if { 
} 
else if { 
} else { 
} 

Основной альтернативой является выключатель (не делают ниже, потому что ничего не получится):

 switch(typeof(PingItemRequestQrMsg)) 
     { 
      case typeof(string): 
       break; 
     } 

, но это приводит к:

 Error 1 A switch expression or case label must be a bool, char, string, integral, enum, or corresponding nullable 

означает, что вы нужен дополнительный уровень по косвенности. Как вы отмечаете каждый класс через интерфейс , например. IMyTag, который возвращает какое-либо перечисление, или присваивает идентификаторы каждому типу с помощью вспомогательной функции.

Серьезно, если обычно не является плохим выбором для такого рода вещей. Часто бывает разумнее переносить с помощью , если, чем терпеть отсутствие проверки типа времени компиляции, которая может возникнуть при использовании коммутатора с использованием строкового подхода. т. е. получить одну букву неправильно, и ваш оператор switch не выглядит таким уж здоровым.

Если в каждой условной ветке есть что-то общее, есть другие варианты.

1

случай переключатель будет лучше:

switch (item.Type) 
{ 
    case typeof(string): 
     // code here 
     break; 
    case typeof(DateTime): 
     // code here 
     break; 
    case typeof(bool): 
     // code here 
     break; 
} 
+0

Случае заявление позволяет только для постоянных значений. Коммутатор позволяет использовать только интегральные типы. Это не скомпилировано с C# – Sascha

+0

Я думал об этом, но я не хочу использовать переключатель. – ukraine

+0

@Sascha, спасибо за дополнительную информацию. –

0

Вы можете построить карту между типами и целыми числами. Затем вы можете включить результат поиска. На SO это еще один вопрос с этим подходом.

скопированную часть одного из ответов:

Dictionary<Type, int> typeDict = new Dictionary<Type, int> 
{ 
    {typeof(int),0}, 
    {typeof(string),1}, 
    {typeof(MyClass),2} 
}; 

void Foo(object o) 
{ 
    switch (typeDict[o.GetType()]) 
    { 
     case 0: 
      Print("I'm a number."); 
      break; 
     case 1: 
      Print("I'm a text."); 
      break; 
     case 2: 
      Print("I'm classy."); 
      break; 
     default: 
      break; 
    } 
} 

Кредиты для этого кода идет в bjax-bjax.

Возможно, вы могли бы подумать об обертывании поиска в функцию, чтобы вернуть значение по умолчанию.

1

Я думаю, что лучше, чтобы реорганизовать свой код следующим образом:

internal class FildMap 
{ 
    public string ExactTargetFild { get; set; } 
    public string DbFild { get; set; } 
    public Type Type { get; set; } 
    public object GetValue(object value) 
    { 
     switch(Type.Name) 
     { 
      case "System.String": 
       // [Code] 
       break; 
      case "System.DateTime": 
       // [Code] 
       break; 
      case "System.Boolean": 
       // [Code] 
       break; 
     } 

     return null; 
    } 


} 

internal static class FildMapProcessor 
{ 
    private static readonly List<FildMap> Map = new List<FildMap>(); 

    static FildMapProcessor() 
    { 
     if (Map.Count == 0) 
     { 
      Map.Add(new FildMap { ExactTargetFild = "Address 1", DbFild = "Address1", Type = typeof(string) }); 
      Map.Add(new FildMap { ExactTargetFild = "Date of birth", DbFild = "DateOfBirth", Type = typeof(DateTime) }); 
      Map.Add(new FildMap { ExactTargetFild = "Wine Beer", DbFild = "pref_WineBeerSpirits", Type = typeof(bool) }); 
     } 
    } 

    public static Attribute[] CreateAttributes(this DataRow row) 
    { 
     var attributes = new List<Attribute>(); 
     foreach (var item in Map) 
     { 
      foreach (var item in Map) 
      { 
       var value = item.GetValue(row[item.DbFild]); 
       if(value != null) 
        attributes.Add(new Attribute { Name = item.ExactTargetFild, Value = value }); 
      } 
     }   

     return attributes.ToArray(); 
    } 
} 
+0

Что произойдет, если вы ошиблись «System.boolean»? – sgtz

+0

, где идет модульное тестирование, я думаю, –

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