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

C#中仅能在函数中抛出异常?自定义异常抛出问题咨询

问题解析与异常处理机制说明

首先明确:C#完全支持在属性的get/set访问器中抛出异常,你遇到的问题不是语法限制,而是属性set访问器的逻辑写反了,导致异常触发条件根本没满足。

1. 为什么set访问器里的异常没触发?

看你的set访问器代码:

public double HoursParked 
{ 
    get => _hoursParked;
    set
        if (_hoursParked > 24) // 这里判断的是旧的字段值,不是要设置的新值!
        {
            throw new ParkingException();
        }
        else
        {
            _hoursParked = Math.Ceiling(value);
        }
}

这段代码的逻辑是:只有当原来的停车时长已经超过24小时时,设置新值才会抛异常。如果原来的_hoursParked≤24,哪怕你传入一个value=30,代码也会直接把_hoursParked改成Math.Ceiling(30)=30,完全不会触发异常判断——这就是你调试时看不到异常的原因。

正确的逻辑应该是先检查要设置的新值value是否非法,再决定是否赋值:

public double HoursParked 
{ 
    get => _hoursParked;
    set
    {
        if (value > 24) // 检查传入的新值
        {
            throw new ParkingException();
        }
        _hoursParked = Math.Ceiling(value);
    }
}

这样只要你试图设置一个超过24小时的值,set访问器就会立刻抛出异常,拦截非法值存入字段。

2. 为什么移到DisplayTotalCost里能触发异常?

你的DisplayTotalCost方法里判断的是当前已经存入的HoursParked值:

public void DisplayTotalCost()
{
    if(HoursParked > 24)
    {
        throw new ParkingException();
    }
}

因为之前set访问器的逻辑错误,允许了超过24的值存入_hoursParked,所以当你调用这个方法时,读取到的当前值已经大于24,自然触发了异常。但这属于事后检查,而属性访问器的设计初衷之一就是事前拦截非法输入,避免非法值被存储。

3. C#异常处理的核心要点

  • 属性的get/set本质上是编译器自动生成的get_HoursParked()和set_HoursParked(double value)方法,和普通方法完全一样,支持抛出异常。.NET类库中也有大量例子,比如索引器List<T>[index]在索引越界时会抛出ArgumentOutOfRangeException。
  • 异常的作用是报告程序运行时的非法状态或错误,不管是在方法、属性访问器还是构造函数里,只要遇到非法情况都可以抛出。
  • 自定义异常建议直接继承Exception,而非ApplicationException——微软后续文档明确说明,ApplicationException的设计初衷并未达成,自定义异常应直接继承基类Exception。

内容的提问来源于stack exchange,提问作者user21279196

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 18:27:31