You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#解析带货币单位的PenaltyRate列计算图书逾期罚款

问题根因

两个Label无内容是代码运行时触发未捕获异常直接中断,没有执行到赋值逻辑导致,具体问题点:

  • 语法逻辑错误:if (dt.Rows.Count >= 1) ; 语句末尾多写了分号,判断逻辑直接失效,查询无结果时访问dt.Rows[0]会抛出索引越界异常
  • 格式转换错误:PenaltyRate列存储的是带货币单位的拼接字符串(如50 USD),直接调用Convert.ToSingle(str)无法识别非数值内容,抛出格式转换异常
  • 日期处理存在隐患:先将DateTime.Now转字符串再转回DateTime的写法容易受系统区域日期格式影响,可能触发日期转换错误
修复步骤
  1. 删除if (dt.Rows.Count >= 1)末尾多余的分号
  2. 新增PenaltyRate数值提取逻辑:按空格拆分字符串,过滤空片段后取第一个片段就是纯数值部分,用安全转换方法转成数值类型
  3. 简化日期计算逻辑,移除冗余的字符串转日期操作,逾期天数可按业务需求取整(不足1天按1天算可使用Math.Ceiling)
  4. 补充异常捕获,避免程序意外中断
修复后完整代码
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 17:54:25