C#动态对象引用:如何简化Mydata方法的非动态赋值逻辑
嘿,我来帮你解决这个if-else冗余的问题!要实现无分支的动态赋值,有两种实用的思路,我给你详细拆解下:
先明确前提
假设你的Data类属性是按规律命名的(比如variable0、variable1、variable2...),就像你代码片段里暗示的那样,先给出这个类的示例:
public class Data { public string variable0 { get; set; } public string variable1 { get; set; } public string variable2 { get; set; } // 可以根据需求扩展更多variableX属性 }
方案一:反射+属性缓存(动态性最强)
利用属性名的规律性,通过反射动态定位属性并赋值,彻底摆脱if-else。为了避免重复反射的性能损耗,我们可以提前缓存属性信息:
public class YourClassName { public List<Data> _newData = new List<Data>(); // 提前缓存Data类的属性,避免每次反射查找 private static readonly Dictionary<int, PropertyInfo> _dataPropertyCache = new Dictionary<int, PropertyInfo>(); // 静态构造函数初始化缓存 static YourClassName() { var dataType = typeof(Data); int index = 0; while (true) { var propertyName = $"variable{index}"; var property = dataType.GetProperty(propertyName); if (property == null) break; // 没有更多属性就停止 _dataPropertyCache.Add(index, property); index++; } } public void Mydata(int number, List<string> listData) { // 先做参数校验,避免索引越界 if (listData == null) throw new ArgumentNullException(nameof(listData)); if (number < 1 || number > _dataPropertyCache.Count) throw new ArgumentOutOfRangeException(nameof(number), "number超出支持的范围"); if (listData.Count < number) throw new ArgumentException("listData的元素数量不足以匹配number的要求"); var newDataItem = new Data(); // 循环赋值,完全替代if-else for (int i = 0; i < number; i++) { if (_dataPropertyCache.TryGetValue(i, out var property) && property.CanWrite) { property.SetValue(newDataItem, listData[i]); } } _newData.Add(newDataItem); } }
为什么这个方案好用?
- 完全没有分支判断,不管number是1还是10(只要有对应的
variableX属性),代码都能自动适配 - 静态构造函数只初始化一次缓存,后续调用的性能损耗几乎可以忽略
- 扩展性极强,新增
variableX属性不需要修改Mydata方法,缓存会自动识别
方案二:委托字典映射(性能最优)
如果你的number取值是固定的几个值(比如只能是1、2、3),可以提前把每个number对应的赋值逻辑封装成委托,存在字典里,调用时直接匹配执行:
public class YourClassName { public List<Data> _newData = new List<Data>(); // 提前定义每个number对应的赋值委托 private static readonly Dictionary<int, Action<Data, List<string>>> _assignActionMap = new Dictionary<int, Action<Data, List<string>>> { { 1, (data, list) => data.variable0 = list[0] }, { 2, (data, list) => { data.variable0 = list[0]; data.variable1 = list[1]; } }, { 3, (data, list) => { data.variable0 = list[0]; data.variable1 = list[1]; data.variable2 = list[2]; } }, // 可以继续添加更多number对应的逻辑 }; public void Mydata(int number, List<string> listData) { if (listData == null) throw new ArgumentNullException(nameof(listData)); if (!_assignActionMap.ContainsKey(number)) throw new ArgumentOutOfRangeException(nameof(number), "不支持该number值"); if (listData.Count < number) throw new ArgumentException("listData的元素数量不足"); var newDataItem = new Data(); // 直接通过字典取委托执行,无任何分支判断 _assignActionMap[number](newDataItem, listData); _newData.Add(newDataItem); } }
这个方案的优势:
- 性能比反射好,因为委托是直接调用属性赋值,没有反射的开销
- 代码可读性高,每个number对应的逻辑一目了然
- 同样摆脱了if-else,符合你要的动态性要求
总结选择建议
- 如果
number的取值范围不固定、Data类的属性会频繁新增,选方案一 - 如果
number是固定的几个值、追求极致性能,选方案二
内容的提问来源于stack exchange,提问作者Skyx
相关产品推荐
相关产品推荐

