C#解析带货币单位的PenaltyRate列计算图书逾期罚款
问题根因
两个Label无内容是代码运行时触发未捕获异常直接中断,没有执行到赋值逻辑导致,具体问题点:
- 语法逻辑错误:
if (dt.Rows.Count >= 1) ;语句末尾多写了分号,判断逻辑直接失效,查询无结果时访问dt.Rows[0]会抛出索引越界异常 - 格式转换错误:PenaltyRate列存储的是带货币单位的拼接字符串(如
50 USD),直接调用Convert.ToSingle(str)无法识别非数值内容,抛出格式转换异常 - 日期处理存在隐患:先将
DateTime.Now转字符串再转回DateTime的写法容易受系统区域日期格式影响,可能触发日期转换错误
修复步骤
- 删除
if (dt.Rows.Count >= 1)末尾多余的分号 - 新增PenaltyRate数值提取逻辑:按空格拆分字符串,过滤空片段后取第一个片段就是纯数值部分,用安全转换方法转成数值类型
- 简化日期计算逻辑,移除冗余的字符串转日期操作,逾期天数可按业务需求取整(不足1天按1天算可使用
Math.Ceiling) - 补充异常捕获,避免程序意外中断
修复后完整代码
try { // using块会自动释放数据库连接,避免资源泄漏 using(SqlConnection con = new SqlConnection(strcon)) { if (con.State == ConnectionState.Closed) { con.Open(); } SqlCommand cmd = new SqlCommand(); cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "getBookIssuing"; cmd.Parameters.Add("@MemberId", SqlDbType.NVarChar).Value = txtMembeReturnId.Text.Trim(); cmd.Parameters.Add("@BookId", SqlDbType.NVarChar).Value = txtReturnBookId.Text.Trim(); cmd.Connection = con; SqlDataAdapter da = new SqlDataAdapter(cmd); DataTable dt = new DataTable(); da.Fill(dt); // 已移除if语句末尾多余的分号 if (dt.Rows.Count >= 1) { // 直接取当天日期,不需要转字符串再转回,避免格式兼容问题 DateTime d1 = DateTime.Now.Date; DateTime d2 = Convert.ToDateTime(dt.Rows[0]["DueDate"]).Date; // 提取PenaltyRate纯数值:按空格拆分、过滤空片段后取第一段,安全转换 string penaltyStr = dt.Rows[0]["PenaltyRate"].ToString(); float dailyPenalty = 0; string[] rateParts = penaltyStr.Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries); if(rateParts.Length >= 1) { float.TryParse(rateParts[0], out dailyPenalty); } if (d1 > d2) { TimeSpan t = d1 - d2; // 逾期天数取整,不足1天按1天计算,不需要小数可直接转int int latedaysno = (int)Math.Ceiling(t.TotalDays); Labellatedays.Text = latedaysno.ToString(); double totalPenalty = latedaysno * dailyPenalty; // 金额默认保留2位小数,可按需调整格式 Labelpenalty.Text = totalPenalty.ToString("0.00"); } else { Labellatedays.Text = "0"; Labelpenalty.Text = "0.00"; } } } } catch(Exception ex) { // 调试阶段可加断点查看ex.Message定位具体问题,正式环境可替换为友好提示 Labellatedays.Text = "计算失败"; Labelpenalty.Text = "计算失败"; }
长期优化建议:建议将PenaltyRate拆分为
PenaltyAmount(数值类型)和CurrencyType(字符串类型)两个独立字段存储,从根源上避免字符串解析带来的转换异常问题。
内容的提问来源于stack exchange,提问作者HeKe
相关产品推荐
相关产品推荐

