开发者

How to get out of repetitive if statements?

开发者 https://www.devze.com 2023-04-10 08:41 出处:网络
While looking though some code of th开发者_开发技巧e project I\'m working on, I\'ve come across a pretty hefty method which does

While looking though some code of th开发者_开发技巧e project I'm working on, I've come across a pretty hefty method which does the following:

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
  }
}

Obviously having 26 if statements just to determine if a property is null and then to update that property and do a database call is probably very naive in implementation. What would be a better way of doing this unit of work?


Thankfully C# is able to inspect and assign class members dynamically, so one option would be to create a map list and iterate over that.

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


You could just loop through all the character from 'A' to 'Z'. It gets difficult because you want to access an attribute of your 'data' object with the corresponding name, but that should (as far as I know) be possible through the C# reflection functionality.

While you get rid of the consecutive if-statements this still won't make your code nice :P


there is a fancy linq solution for your problem using reflection:

but as it was said before: your datastructure is not very well thought through

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 like that you get the property but the update is not yet done.


var data = _dataRepository.Find(id);

If possible, you should use another DataType without those 26 properties. That new DataType should have 1 property and the Find method should return an instance of that new DataType; then, you could get rid of the 26 if in a more natural way.

To return "A", "B" ... "Z", you could use this:

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

And work with some transformation from data.Value to a number between 65 and 90 (A to Z).


Since you always set the lowest alphabet field first and return, you can use an additional field in your class that tracks the first available field. For example, this can be an integer lowest_alphabet_unset and you'd update it whenever you set data.{X}:

Init:

lowest_alphabet_unset = 0;

In 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';
    [...]
}


N.B. -- do not use, if data is object rather that structure.

what comes to my mind is that, if A-Z are all same type, then you could theoretically access memory directly to check for non null values.

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

not tested but to give an idea ;)

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号