使用不同条件重构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
条件
我该如何解决此问题?
只是一个快速警告-以下两项都不是重构,只是重写现有内容的方法。考虑到条件的可变性质及其强加的顺序(例如,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组合更可读、更可维护,更容易直接写出来……但这只是我的两分钱!