删除“if”语句时出现问题

时间:2011-08-03 04:36:06

标签: c# refactoring

您好,

我正试图找到如何改进此代码的方法。 我想从CreateAttributes方法中删除“if”语句。 如果此属性满足某些条件,则此方法的主要思想是将属性添加到列表

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

谢谢,

5 个答案:

答案 0 :(得分: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();
}

答案 1 :(得分:1)

案件开关会更好:

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

答案 2 :(得分: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();
    }
}

答案 3 :(得分:0)

第一个质量改进是使用 else if 。对于发布的示例,这意味着同样的事情,但要更清楚一点。

对于这类事情,我更喜欢使用 if

e.g。

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返回某种枚举,或者通过辅助函数为每种类型指定id。

说真的,如果通常不是这种事情的坏选择。通常使用 if 比忍受编译时类型检查的缺乏更容易,这可能是由使用字符串方法的开关引起的。即得到一个字母错误,你的开关语句似乎不再那么酷了。

如果每个条件分支内部都有通用的东西,还有其他选项。

答案 4 :(得分: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。

也许您可以考虑将查找包装到函数中以返回默认值。