记一次 C# StackOverflowException 异常

本文记录了一次在学习C#属性时遇到的StackOverflowException异常,详细解释了错误原因——属性get和set的无限递归,并提供了两种解决方案:使用私有字段存储数据和直接使用自动属性。同时,对比了两种方法的优缺点,强调了属性在提供灵活性和数据验证方面的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

记一次 C# StackOverflowException 异常

背景

在看刘铁猛老师的《C# 语言入门详解》的第17讲的时候,在 45:00 处,学习属性的 Get/Set 函数,和老师一样的代码,但是老师的没有出错,我的程序在运行的时候却报出了

System.StackOverflowException:“Exception_WasThrown”

错误。

涉及到的代码如下:

public int Score       // 创建一个属性
{
    get
    {
        return Score;
    }
    set
    {
        if(value >= 0 && value <= 100)
        {
            Score = value;
        }
        else
        {
            throw new Exception("输入的分数不对!");
        }
    }
}

错误原因分析

经过查询得知,这个错误的原因是当使用set()设置 Score 属性的时候,会循环调用 set() 函数, set() 函数循环调用 set() 函数… 最终导致堆栈溢出。属性值获取的 get 方法,返回的是属性值本身,这属于递归循环了,导致堆栈溢出。Stack Overflow 上的原文如下:

When setting the price property, you invoke the setter, which invokes the setter which invokes the setter, etc…

解决办法

方法一:设置一个 private 属性名称相近的字段(field)来用于存储

废话不多说,直接看代码:

private int _Score;     // 字段
public int Score        // 属性
{
    get
    {
        return _Score;
    }
    set
    {
        if(value >= 0 && value <= 100)
        {
            _Score = value;
        }
        else
        {
            throw new Exception("输入的分数不对!");
        }
    }
}

这里定义一个私有的字段存储属性值,get 方法返回私有的值。属性没有存储数据的功能,数据都存在字段中,所以只有修改字段的数据才能更改数据,修改属性的值没用。

属性的作用:
  • 属性更灵活
  • 属性是一种方法
  • 属性实际是用来给字段赋值的,如果愿意的话。

方法二:直接设置 { get; set; }

代码如下:

public int Score { get; set; } // 可以正常使用,不会报错

总结

方法一感觉比较繁琐,但是方法二不能在接收值的时候进行初步的判断,有可能会接收到非法的值(不合常理的值,比如年龄200岁等)。方法二是 C# 的语法糖。

最终重新看视频中的代码发现,老师除了声明这个属性之外,还声明了一个字段,但是首字母是小写的。所以属于看错了,但是也因此加深了一下对字段(field)和属性(property)的理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值