列名验证函数误抛异常:如何正确校验合法列名
列名合法性校验逻辑修复方案
问题背景
以下C#代码用于列名合法性校验,但当前ValidateColumns函数存在两个严重问题:
- 逻辑运算符误用,导致合法列名也会抛出
KeyNotFoundException - 未支持带指定前缀(
DD -、MD -、DT -、RT -、FT -)的合法列校验
原代码:
List<string> columnNames = new List<string>(); // 合法列名 columnNames.Add("IDRef"); columnNames.Add("RiskAssessmentTitle"); columnNames.Add("RiskAssessmentDate"); columnNames.Add("RiskAssessmentLabel"); columnNames.Add("Likelihood"); columnNames.Add("Impact"); // 带指定前缀的合法列名 columnNames.Add("DD - IDRef"); columnNames.Add("MD - RiskAssessmentTitle"); columnNames.Add("DT - RiskAssessmentDate"); columnNames.Add("RT - RiskAssessmentLabel"); columnNames.Add("FT - Likelihood"); columnNames.Add("FT - Impact"); // 非法列名 columnNames.Add("IDRefIDref"); columnNames.Add("RiskAssessmentTitle-title"); columnNames.Add("RiskAssessmentDate-title"); columnNames.Add("RiskAssessmentLabel-lable"); columnNames.Add("Likelihood-something"); columnNames.Add("Impact-impact-impact"); // 校验循环 foreach(string columnName in columnNames){ await ValidateColumns(columnName); } async Task ValidateColumns(string columnName, int i) { columnName.Trim(); if (!columnName.EndsWith("IDRef") || !columnName.EndsWith("RiskAssessmentTitle") || !(columnName.EndsWith("RiskAssessmentDate")) || !(columnName.EndsWith("RiskAssessmentLabel")) || !(columnName.EndsWith("Likelihood")) || !(columnName.EndsWith("Impact"))) throw new KeyNotFoundException("ImportInvalidFieldRowNumber"); }
问题分析
- 逻辑运算符错误:原判断使用
||(逻辑或),意味着只要列名不匹配任意一个后缀就抛出异常——完全违背需求,应该用&&(逻辑与),即列名不匹配所有合法后缀时才判定为非法。 - 未处理前缀规则:原代码未识别带指定前缀+合法后缀的列名。
- 字符串操作无效:
columnName.Trim()未赋值回变量,string是不可变类型,该操作不会修改原变量。 - 参数不匹配:调用
ValidateColumns(columnName)时只传了一个参数,但函数定义要求两个,会编译报错。
修复后的代码
List<string> columnNames = new List<string>(); // 合法列名 columnNames.Add("IDRef"); columnNames.Add("RiskAssessmentTitle"); columnNames.Add("RiskAssessmentDate"); columnNames.Add("RiskAssessmentLabel"); columnNames.Add("Likelihood"); columnNames.Add("Impact"); // 带指定前缀的合法列名 columnNames.Add("DD - IDRef"); columnNames.Add("MD - RiskAssessmentTitle"); columnNames.Add("DT - RiskAssessmentDate"); columnNames.Add("RT - RiskAssessmentLabel"); columnNames.Add("FT - Likelihood"); columnNames.Add("FT - Impact"); // 非法列名 columnNames.Add("IDRefIDref"); columnNames.Add("RiskAssessmentTitle-title"); columnNames.Add("RiskAssessmentDate-title"); columnNames.Add("RiskAssessmentLabel-lable"); columnNames.Add("Likelihood-something"); columnNames.Add("Impact-impact-impact"); // 校验循环(修正参数传递,行号用于异常定位) for(int i = 0; i < columnNames.Count; i++){ await ValidateColumns(columnNames[i], i); } async Task ValidateColumns(string columnName, int rowNumber) { // 修正Trim操作,赋值回变量生效 string trimmedName = columnName.Trim(); // 定义合法后缀集合,提升查询效率 var validSuffixes = new HashSet<string> { "IDRef", "RiskAssessmentTitle", "RiskAssessmentDate", "RiskAssessmentLabel", "Likelihood", "Impact" }; // 定义合法前缀集合 var validPrefixes = new HashSet<string> { "DD - ", "MD - ", "DT - ", "RT - ", "FT - " }; // 校验逻辑: // 1. 列名本身是合法后缀,OR // 2. 列名以合法前缀开头,且前缀后的部分是合法后缀 bool isValid = validSuffixes.Contains(trimmedName) || validPrefixes.Any(prefix => trimmedName.StartsWith(prefix) && validSuffixes.Contains(trimmedName.Substring(prefix.Length))); // 非法时抛出异常,携带行号信息便于定位 if (!isValid) { throw new KeyNotFoundException($"ImportInvalidFieldRowNumber: {rowNumber}"); } }
修复说明
- 逻辑修正:用
HashSet存储合法后缀和前缀,通过Contains和Any组合判断列名是否符合规则,避免原逻辑的运算符误用问题。 - 前缀规则支持:新增前缀校验逻辑,判断列名是否为「合法前缀+合法后缀」的组合。
- 字符串操作修复:将
Trim后的结果赋值给新变量,确保去空格操作生效。 - 参数与异常优化:修正参数匹配问题,异常信息携带行号,方便定位非法列的位置。
内容的提问来源于stack exchange,提问作者San Jaisy
相关产品推荐
相关产品推荐

