如何摆脱重复的if语句?

时间:2011-10-04 16:20:31

标签: algorithm c#-4.0 if-statement

虽然看一下我正在研究的项目的一些代码,但我遇到了一个非常重要的方法, 以下内容:

public string DataField(int id, string fieldName)
{
   var data = _dataRepository.Find(id);
   if (data != null)
  {
      if (data.A == null)
      {
        data.A = fieldName;
        _dataRepository.InsertOrUpdate(data);
        return "A";
      }

      if (data.B == null)
      {
        data.B = fieldName;
        _dataRepository.InsertOrUpdate(data);
        return "B";
      }

    // keep going data.C through data.Z  doing the exact same code
  }
}

显然有26个if语句只是为了确定属性是否为null然后更新该属性并进行数据库调用 在实施中可能非常天真。做这个工作单元的更好方法是什么?

6 个答案:

答案 0 :(得分:3)

谢天谢地C# is able to inspect and assign class members dynamically,所以一个选项就是创建一个 map 列表并迭代它。

    public string DataField(int id, string fieldName)
    {
        var data = _dataRepository.Find(id);

        List<string> props = new List<string>();
        props.Add("A");
        props.Add("B");
        props.Add("C");

        if (data != null)
        {
            Type t = typeof(data).GetType();
            foreach (String entry in props) {
                PropertyInfo pi = t.GetProperty(entry);
                if (pi.GetValue(data) == null) {
                    pi.SetValue(data, fieldName);
                    _dataRepository.InsertOrUpdate(data);
                    return entry;
                }
            }
        }
    }

答案 1 :(得分:1)

你可以循环遍历从'A'到'Z'的所有角色。这很难,因为你想用相应的名称访问你的'data'对象的属性,但是(据我所知)这应该可以通过C#反射功能。

当你摆脱连续的if语句时,这仍然不会使你的代码变得更好:P

答案 2 :(得分:1)

使用反射为您的问题提供了一个花哨的linq解决方案:

但正如之前所说的那样:您的数据结构没有经过深思熟虑

public String DataField(int id, string fieldName)
{
    var data = new { Z = "test", B="asd"};
    Type p = data.GetType();

    var value = (from System.Reflection.PropertyInfo fi 
                     in p.GetProperties().OrderBy((fi) => fi.Name)
                     where fi.Name.Length == 1 && fi.GetValue(data, null) != null 
                     select fi.Name).FirstOrDefault();
    return value;
}
ta taaaaaaaaa 就像你得到了财产但更新尚未完成。

答案 3 :(得分:0)

由于您始终先设置最低字母字段并返回,因此您可以在班级中使用跟踪第一个可用字段的其他字段。例如,这可以是整数lowest_alphabet_unset,您可以在设置数据时更新它。{X}:

初​​始化:

lowest_alphabet_unset = 0;

在DataField中:

lowest_alphabet_unset ++;
switch (lowest_alphabet_unset) {

    case 1: 
        /* A is free */
        /* do something */
        return 'A';
    [...]

    case 7:
        /* A through F  taken */
        data.G = fieldName;
        _dataRepository.InsertOrUpdate(data);
        return 'G';
    [...]
}

答案 4 :(得分:0)

var data = _dataRepository.Find(id);

如果可能,您应该使用另一个没有这26个属性的DataType。新的DataType应该有1个属性,而Find方法应该返回该新DataType的实例;那么,如果以更自然的方式,你可以摆脱26。

要返回“A”,“B”......“Z”,您可以使用:

return (char)65; //In this example this si an "A"

使用从data.Value到65到90之间的数字(A到Z)的转换。

答案 5 :(得分:-1)

<强> N.B。 - 如果数据是对象而不是结构,请不要使用。

我想到的是,如果A-Z都是相同的类型,那么理论上你可以直接访问内存以检查非空值。

start = &data;

for (i = 0; i < 26; i++){
   if ((typeof_elem) *(start + sizeof(elem)*i) != null){
      *(start + sizeof(elem)*i) = fieldName;
      return (char) (65 + i);
   }
}

没有经过测试,但提出了一个想法;)