SonarQube检测出严重代码异味,求多OR条件代码优化方案
重构方案:用规则映射简化多OR条件判断
针对这段充斥大量StartsWith和OR判断的代码,我们可以通过规则映射字典+委托判断的方式重构,彻底消除冗余的if-else分支,同时提升代码的可维护性与可读性。
实现思路
把每个返回值对应的匹配逻辑封装成Func<string, bool>委托,集中存储在字典中。遍历字典时找到第一个匹配规则的项,直接返回对应的结果字符串。这种方式将分散的判断逻辑统一管理,新增或修改规则仅需调整字典项,无需改动分支结构。
重构后的代码
// 预先定义规则映射:键为返回结果,值为对应的匹配逻辑 private static readonly Dictionary<string, Func<string, bool>> _policyTypeRules = new Dictionary<string, Func<string, bool>> { {"POLICIES", p => p.StartsWith("CM")}, {"ANNUITY", p => p.StartsWith("W002")}, {"VARIABLE ANNUITY", p => p.StartsWith("W007")}, {"INT POLICIES", p => p.StartsWith("H0032") || (p.Length == 10 && char.IsDigit(p[0]) && p[0] >= '1' && p[0] <= '4') }, {"WS POLICIES", p => new[] {"W003", "W004", "W008"}.Any(prefix => p.StartsWith(prefix)) || (p.StartsWith("0000") && p.Length == 11) } }; // 核心判断方法 public string GetPolicyType(string policyNumber) { foreach (var rule in _policyTypeRules) { if (rule.Value(policyNumber)) { return rule.Key; } } // 可根据业务需求设置默认返回值,比如返回空字符串或抛出异常 return string.Empty; }
优化细节说明
- 简化数字开头判断:原代码中
StartsWith("1") || StartsWith("2") ...替换为char.IsDigit(p[0]) && p[0] >= '1' && p[0] <= '4',既简洁又避免重复调用StartsWith。 - 批量前缀判断:对于W003/W004/W008这类同类型前缀,用数组结合
Any方法一次性判断,减少重复的OR条件。 - 规则集中管理:所有匹配逻辑都在字典中定义,后续新增政策类型只需添加新的字典项,无需修改判断方法结构,符合开闭原则。
扩展方案:策略模式(复杂场景适用)
如果后续规则逻辑变得更复杂(比如需要不同的匹配算法),可以进一步用策略模式拆分:
// 定义策略接口 public interface IPolicyTypeMatcher { bool Matches(string policyNumber); string PolicyType { get; } } // 实现具体策略 public class CmPolicyMatcher : IPolicyTypeMatcher { public string PolicyType => "POLICIES"; public bool Matches(string policyNumber) => policyNumber.StartsWith("CM"); } public class IntPolicyMatcher : IPolicyTypeMatcher { public string PolicyType => "INT POLICIES"; public bool Matches(string policyNumber) { return policyNumber.StartsWith("H0032") || (policyNumber.Length == 10 && char.IsDigit(policyNumber[0]) && policyNumber[0] >= '1' && policyNumber[0] <= '4'); } } // 策略容器 public class PolicyTypeResolver { private readonly List<IPolicyTypeMatcher> _matchers; public PolicyTypeResolver() { _matchers = new List<IPolicyTypeMatcher> { new CmPolicyMatcher(), new AnnuityPolicyMatcher(), // 其他策略类按需实现 new VariableAnnuityPolicyMatcher(), new IntPolicyMatcher(), new WsPolicyMatcher() }; } public string GetPolicyType(string policyNumber) { var matcher = _matchers.FirstOrDefault(m => m.Matches(policyNumber)); return matcher?.PolicyType ?? string.Empty; } }
这种方式适合规则逻辑复杂、需要单独维护每个匹配逻辑的场景,代码扩展性更强。
内容的提问来源于stack exchange,提问作者jansy
相关产品推荐
相关产品推荐

