0
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 错误吗?我的意思是,低级的东西。

堆栈溢出!

4

9 回答 9

13

你是TotalCount从内部调用的TotalCount,不要那样做。

您可以为属性值设置另一个字段。

不过,我怀疑您的代码应为:

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

编辑:至于为什么会发生 stackoverflow,这是因为当您使用 Properties 时,.NET 编译器实际上会生成 2 个函数,set_PropertyName并且get_PropertyName. 所以从本质上讲,它会导致get_PropertyName方法调用的堆栈溢出变得无限深。

于 2012-08-22T20:39:37.560 回答
4

查看正在发生的事情(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()应该很清楚了。该方法无条件地调用自身,因此最终会炸毁堆栈。

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

于 2012-08-22T20:43:33.440 回答
3

有人可以详细解释为什么会发生 SO 错误吗?

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

  • 得到UnassignedCount
  • 得到TotalCount
  • 添加UnassignedCountTotalCount
  • 返回结果

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

于 2012-08-22T20:43:25.257 回答
2

你应该可以这样写:你应该注意 TotalCount 永远不能被设置为所以它没有价值。您是否可能打算这样做:

public class ModelInfo
{
    public int AssignedCount { get; set; }
    public int UnassignedCount { get; set; }
    public int TotalCount { get { return UnassignedCount + AssignedCount; } }
}
于 2012-08-22T20:47:49.580 回答
1

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

堆栈是内存的固定分配,因此您只能调用这么多级别,然后才能用完存储在函数返回时恢复 CPU 寄存器状态所需的信息。此时,发生堆栈溢出错误,因为您溢出了堆栈。您进行了如此多的嵌套调用,以至于内存不足,无法将它们记录下来。

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

于 2012-08-22T20:43:12.283 回答
0

因为您指TotalCount的是TotalCount吸气剂内部。无限循环发生,直到达到堆栈溢出。

于 2012-08-22T20:40:20.670 回答
0

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

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

  • 获取 UnassignedCount 的值
  • 获取 Totalcount 的值

重复,冲洗和清洗。

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

于 2012-08-22T20:40:56.927 回答
0

你在一个无限递归中,一个自称的属性

于 2012-08-22T20:41:09.463 回答
0

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

于 2012-08-22T20:41:31.350 回答