如何清理C#方法中的重复元素?.NET Core 3.1代码重构
优化方案
方案一:提取重复逻辑到私有方法
把每个属性的比较、更新逻辑封装成私有方法,消除重复代码的同时保持主方法的可读性:
public string Name { get; set; } public string Description { get; set; } // 其他string类型属性... public bool MyMethod(Apple myApple) { var flag = false; myApple.Id = Id; // 调用私有方法处理每个属性,用|=累积更新状态 flag |= UpdateProperty(ref Name, myApple.Name); flag |= UpdateProperty(ref Description, myApple.Description); flag |= UpdateProperty(ref ShortDescription, myApple.ShortDescription); flag |= UpdateProperty(ref Location, myApple.Location); flag |= UpdateProperty(ref KindId, myApple.KindId); flag |= UpdateProperty(ref Expiration, myApple.Expiration); flag |= UpdateProperty(ref PurchaseDate, myApple.PurchaseDate); return flag; } // 封装单个属性的比较与更新逻辑 private bool UpdateProperty(ref string target, string source) { if (target != source) { target = source; return true; } return false; }
这种方式完全保留原逻辑,同时将重复的if块收拢到一个方法中,后续修改逻辑只需调整私有方法即可。
方案二:使用反射批量处理属性
如果后续会频繁新增属性,反射方案可以自动匹配当前类与Apple类的同名string属性,避免每次修改MyMethod:
public string Name { get; set; } public string Description { get; set; } // 其他string类型属性... public bool MyMethod(Apple myApple) { var flag = false; myApple.Id = Id; // 获取当前类所有可写的string属性 var currentProps = GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance) .Where(p => p.PropertyType == typeof(string) && p.CanWrite); foreach (var prop in currentProps) { // 匹配Apple类中同名的string属性 var appleProp = typeof(Apple).GetProperty(prop.Name); if (appleProp == null || appleProp.PropertyType != typeof(string)) continue; var currentValue = (string)prop.GetValue(this); var appleValue = (string)appleProp.GetValue(myApple); if (currentValue != appleValue) { prop.SetValue(this, appleValue); flag = true; } } return flag; }
注意事项:
- 反射存在轻微性能开销,适合属性较多或频繁变动的场景;若方法是高频调用,方案一更合适。
- 需保证当前类与
Apple类的属性名完全一致,否则无法自动匹配。
方案三:表达式树缓存(兼顾性能与灵活性)
如果想同时拥有反射的灵活性和直接调用的性能,可以用表达式树提前编译属性的读写方法并缓存:
// 静态缓存,避免重复编译表达式 private static readonly Dictionary<Type, Dictionary<string, (Func<object, string> Getter, Action<object, string> Setter)>> _propertyAccessors = new(); public string Name { get; set; } public string Description { get; set; } // 其他string类型属性... public bool MyMethod(Apple myApple) { var flag = false; myApple.Id = Id; var currentType = GetType(); var appleType = typeof(Apple); // 初始化当前类的属性访问器缓存 if (!_propertyAccessors.ContainsKey(currentType)) { _propertyAccessors[currentType] = currentType.GetProperties(BindingFlags.Public | BindingFlags.Instance) .Where(p => p.PropertyType == typeof(string) && p.CanWrite) .ToDictionary( p => p.Name, p => ( Getter: CreateGetter(p), Setter: CreateSetter(p) ) ); } // 初始化Apple类的属性访问器缓存 if (!_propertyAccessors.ContainsKey(appleType)) { _propertyAccessors[appleType] = appleType.GetProperties(BindingFlags.Public | BindingFlags.Instance) .Where(p => p.PropertyType == typeof(string)) .ToDictionary( p => p.Name, p => ( Getter: CreateGetter(p), Setter: null // Apple类仅需读取属性 ) ); } var currentAccessors = _propertyAccessors[currentType]; var appleAccessors = _propertyAccessors[appleType]; foreach (var (propName, currentAccessor) in currentAccessors) { if (!appleAccessors.TryGetValue(propName, out var appleAccessor)) continue; var currentValue = currentAccessor.Getter(this); var appleValue = appleAccessor.Getter(myApple); if (currentValue != appleValue) { currentAccessor.Setter(this, appleValue); flag = true; } } return flag; } // 创建属性的Getter表达式并编译 private static Func<object, string> CreateGetter(PropertyInfo prop) { var param = Expression.Parameter(typeof(object)); var castParam = Expression.Convert(param, prop.DeclaringType); var getProp = Expression.Property(castParam, prop); var castResult = Expression.Convert(getProp, typeof(string)); return Expression.Lambda<Func<object, string>>(castResult, param).Compile(); } // 创建属性的Setter表达式并编译 private static Action<object, string> CreateSetter(PropertyInfo prop) { var instanceParam = Expression.Parameter(typeof(object)); var valueParam = Expression.Parameter(typeof(string)); var castInstance = Expression.Convert(instanceParam, prop.DeclaringType); var castValue = Expression.Convert(valueParam, prop.PropertyType); var setProp = Expression.Assign(Expression.Property(castInstance, prop), castValue); return Expression.Lambda<Action<object, string>>(setProp, instanceParam, valueParam).Compile(); }
该方案首次调用时编译表达式并缓存,后续调用性能接近直接代码调用,同时保留了自动处理属性的灵活性。
内容的提问来源于stack exchange,提问作者Bender.
相关产品推荐
相关产品推荐

