堆栈溢出异常是当执行堆栈可用的有限内存耗尽时引发的.NET异常(错误)。这几乎总是由无限递归引起,最终导致嵌套方法调用过多。
以下代码在尝试设置值时会抛出堆栈溢出异常。
public String Name
{
get{return Name;}
set{Name = value;}
}
我知道引用存储在堆栈中(此处为其名称),对象存储在堆(String对象)中。这个地方的内存使用量是多少?谁能告诉我幕后发生的事情(内部实施细节)?支持领域的必要性是什么?
答案 0 :(得分:4)
当您创建getter的代码{return Name;}
时,您正在递归。怎么样?当某些代码想要获得Name
的值时,您的getter方法只会告诉它,“为什么不再尝试再问我一次?”查看问题?当你尝试获得一个值时,它会告诉你需要再次问自己。然后再次。再一次!
每次访问属性并调用getter时,都会向堆栈添加一个新条目。由于这段代码只会告诉其他代码不断尝试,堆栈无限地变得更加占用! (每当你调用一个方法时,比如你的getter,一个条目被添加到堆栈中)
此外,您更新的问题询问为什么setter会导致堆栈溢出。这和以前几乎一样; 当调用Name
的setter时,它会自行调用。简单的引用来解释? Name
在回复您的代码时说:“如果您想设置我的价值,请尝试重新设置我的价值?”
它在哪里这样做?在Name = value;
。你会尝试设置值,但你的方法会告诉它再次设置自己。然后再次。再一次。
我们如何解决这个问题?正如另一个回答者所示,您可以创建另一个存储实际内容的变量。例如,Name
将包含成功操作数据的getter和setter。但它不会将其存储在自身中,以避免无限递归。它会将其存储在另一个变量中,例如_Name
。
答案 1 :(得分:3)
在C#中,property是一对方法的语法糖:get_PropertyName
和set_PropertyName
(如果属性是只读或只写,则不会生成相应的方法)。您的代码将由编译器转换为:
public string get_Name()
{
return get_Name();
}
public void set_Name(string value)
{
set_Name(value);
}
看看getter和setter,你会看到纯粹的递归。 因此,每次您尝试访问该属性(无论是获取还是设置),您都将调用递归方法。
答案 2 :(得分:0)
使用此
string _name;
public string Name{
get{ return _name; }
set{ _name=value; }
}
OR
public string Name{get;set;}