C# – 属性导致StackOverflow

public class ModelInfo { public int AssignedCount { get; set; } public int UnassignedCount { get; set; } public int TotalCount { get { return UnassignedCount + TotalCount; } } } 

* 编辑: *我意识到当我把这个代码放在SO中时,TotalCount属性正在添加UnassignedCount + TotalCount(我的意思是将其他两个计数加在一起)。 有人可以提供一个足够的解释为什么SO错误发生? 我的意思是,低级别的东西。

Stackoverflowing!

你在TotalCount调用TotalCount ,不要这样做。

您可以使用另一个字段来代替该属性的值。

虽然,我怀疑你的代码应该是:

 public int TotalCount { get { return UnassignedCount + AssignedCount ; } } 

编辑:至于set_PropertyName get_PropertyName发生的原因,这是因为当你使用Properties时,.NET编译器实际上会生成2个函数, set_PropertyNameget_PropertyName 。 所以在essense中,它会导致get_PropertyName方法调用的get_PropertyName变得无限深。

查看正在发生的事情(IMO)的最简单方法是将这些属性转换为方法:

 // If we didn't have properties, this is what the two first lines would be. Ick! private int assignedCount; private int unassignedCount; public int GetAssignedCount() { return assignedCount; } public void SetAssignedCount(int value) { assignedCount = value; } public int GetUnassignedCount() { return unassignedCount; } public void SetUnassignedCount(int value) { unssignedCount = value; } // And here's the read-only TotalCount property translation public int GetTotalCount() { return GetUnassignedCount() + GetTotalCount(); } 

现在GetTotalCount()的递归应该非常清楚。 该方法无条件地调用自身,因此最终炸毁堆栈。

自动实现的属性和属性访问看起来像字段访问这一事实的混合有时会妨碍记住它们实际上只是伪装的方法。 希望上面的翻译更加明显。

有人可以提供一个足够的解释为什么SO错误发生?

当然:为了计算TotalCount ,编译器生成如下代码:

  • 获取UnassignedCount
  • 获取TotalCount
  • UnassignedCount添加到TotalCount
  • 返回结果

在调用TotalCount的属性getter时(记住,getter是一个使用特殊语法的常规无参数函数),运行时将返回地址放在堆栈上。 第二步在开始时找回我们,在堆栈上有一个额外的返回地址; 第三步再做一次,然后是第四步,第五步,依此类推。 每次调用都会在堆栈上存放另一个返回地址。 这一直持续到堆栈的限制,此时抛出exception。

你应该能够这样写:你应该注意到TotalCount永远不能被设置为没有价值。 你是否意味着这样做:

 public class ModelInfo { public int AssignedCount { get; set; } public int UnassignedCount { get; set; } public int TotalCount { get { return UnassignedCount + AssignedCount; } } } 

有一种称为“堆栈”的机制,用于跟踪嵌套调用。 当您调用方法或函数时,当前的“堆栈帧”(控件将在您调用的方法返回时转移到的地址,以及方法中的任何参数和方法本地)被压入堆栈。 当控制返回到您的方法时,弹出此堆栈帧并将CPU寄存器恢复到其先前状态,以便您的方法可以继续执行。

堆栈是固定的内存分配,因此您只能在用完地方之前调用这么多级别来存储恢复函数时恢复CPU寄存器状态所需的信息。 此时,发生堆栈溢出错误,因为您溢出堆栈。 您进行了如此多的嵌套调用,而内存不足以将其记录下来。

这就是exception发生的原因。 你无限地递归:你的属性getter一遍又一遍地调用自己,直到堆栈上没有空间。

因为您指的是TotalCount getter中的TotalCount 。 发生无限循环,直到达到堆栈溢出。

在尝试获取TotalCount的值时,您正在循环

粗略地说,获得TotalCount的逻辑是:

  • 获取UnassignedCount的值
  • 获得Totalcount的价值

重复,冲洗和清洗。

编辑:至于为什么,看看维基

你是一个无限的递归,一个自称的财产

因为调用堆栈(理论上)会无限深入。 并且您没有无限堆栈来保存您需要的所有数据。