使用不同条件重构if语句

本文关键字:重构 if 语句 条件 | 更新日期: 2023-09-27 18:21:17

我正在尝试重构一个由多个具有不同条件的if语句组成的方法。方法如下:

private void DeserializeProperty(object value, 
                                 PropertyInfo property, Format format) {
     if (value == DBNull.Value || value == null) {
        property.SetValue(this, null);
        return;
     }
     if (property.PropertyType == typeof(Id)) {
        SetIdProperty(value, property);
        return;
     }
     if (property.PropertyType.BaseType == typeof(BaseProperty)) {
        SetBaseProperty(value, property);
        return;
     }
     if (property.PropertyType == typeof(Data)) {
        DeserializeData(value, property, format);
        return;
     }
     DeserializeNormalProperty(property, value);
}

用多态性替换这些If语句是不可行的(不确定如果可行的话这样做是否明智),因为条件与PropertyType 有关

Dictionery<Type,Action<object, PropertyInfo>>类型的Dictionary替换它们是不起作用的,因为该方法DeserializeData(value, property, format);不适合

此外,上述解决方案中没有一个将处理value == DBNull.Value || value == null条件

我该如何解决此问题?

使用不同条件重构if语句

只是一个快速警告-以下两项都不是重构,只是重写现有内容的方法。考虑到条件的可变性质及其强加的顺序(例如,baseproperty的basetype优先于数据),很难想象有什么比if-else更好或更清晰的了。IMO仅仅重构一个函数是无法真正改进现有功能的。但无论如何,我都会提出一些可能的重写,以防任何一方上诉。

可以使用elses(只是为了可读性):

注意:根据一些编码准则,这比您现有的更不优惠。然而,就我个人而言,我觉得它可读性更强

private void DeserializeProperty(object value, 
                                 PropertyInfo property, Format format) {
    if (value == DBNull.Value || value == null) {
         property.SetValue(this, null);
    }
    else if (property.PropertyType == typeof(Id)) {
         SetIdProperty(value, property);
    }
    else if (property.PropertyType.BaseType == typeof(BaseProperty)) {
         SetBaseProperty(value, property);
    }
    else if (property.PropertyType == typeof(Data)) {
         DeserializeData(value, property, format);
    }
    else {
         DeserializeNormalProperty(property, value);
    }
 }

备选方案(如果您愿意)

如果您正在进行许多类似的切换,请使用类似于以下内容的自定义CleverSwitch类:

https://stackoverflow.com/a/299120/3940783

可能对你有用。这与你对Actions字典的想法非常相似,但由于你的条件不同,最干净的做法是让Actions没有输入,只使用DeserializeProperty作用域中的变量,而不将它们传递到操作中。

因此,例如,您可以用以下内容替换该功能:

private void DeserializeProperty(object value, 
                                 PropertyInfo property, Format format) {
    CleverSwitch.Do(
        CleverSwitch.If(() => value == DBNull.Value || value == null, () => property.SetValue(this, null))
        CleverSwitch.IsType<Id>(property.PropertyType, () => SetIdProperty(value, property)),
        CleverSwitch.IsType<BaseProperty>(property.PropertyType.BaseType, () => SetBaseProperty(value, property)),
        CleverSwitch.IsType<Data>(property.PropertyType, () => DeserializeData(value, property, format)),
        CleverSwitch.Default(() => DeserializeNormalProperty(property,value))
    );
}

CleverSwitch的工作原理与JaredPar的TypeSwitch在上述链接中的工作原理类似,并且可以编码如下:

static class CleverSwitch {
    public class CaseInfo {
        public Func<bool> Condition { get; set; }
        public Action Action { get; set; }
    }
    public static void Do(object source, params CaseInfo[] cases) {
        var type = source.GetType();
        foreach (var entry in cases) {
            if (entry.Condition()) {
                entry.Action();
                break;
            }
        }
    }
    public static CaseInfo IsType<T>(Type T2, Action action) {
        return new CaseInfo() { Condition = () => T2 == typeof(T), Action = action };
    }
    public static CaseInfo If(Func<bool> condition, Action action) {
        return new CaseInfo() { Condition = condition, Action = action };
    }
    public static CaseInfo Default(Action action) {
        return new CaseInfo() { Condition = () => true, Action = action };
    }
}

但总的来说:

在这种情况下,任何帮助您以字典方法重构它的类都必须相当通用,因此本质上只是令人困惑并增加性能开销。因此,虽然上面的代码应该可以工作,但我真的看不出它在以下任何领域如何改进if语句:

  • 写入时间
  • 可读性
  • 可维护性

事实上,我认为简单的if、return或if、else组合更可读、更可维护,更容易直接写出来……但这只是我的两分钱!