为什么会导致StackOverFlow错误?

时间:2009-12-18 16:12:25

标签: c# .net

这导致了StackOverFlow错误,我知道为什么,但我想了解更多关于原因的详细信息,并且是我应该如何处理它的解决方案。好的,首先,当我尝试为属性赋值时,以下代码会导致StackOverFlow错误:

private List<Albums> albums
{
    get
    {
        if (Session["albums"] != null)
            return (List<Albums>)Session["albums"];
        else
            return AlbumCollection.GetAlbums();
    }
    set
    {
    albums = value;
    Session["albums"] = albums;
    }
}

为解决上述问题,我更改了属性的名称,并添加了另一个变量来保存解决StackOverFlow问题的属性值:

private List<Albums> albums = null;
private List<Albums> Albums
{
    get
    {
        if (Session["albums"] != null)
            return (List<Albums>)Session["albums"];
        else
            return AlbumCollection.GetAlbums();
    }
    set
    {
    albums = value;
    Session["albums"] = albums;
    }
}

另外,我是否正确设置了setter,分配了值,然后将Session [“albums”]分配给相册中的值?我可以刚刚完成,会话[“专辑”] =值而不是吗?

9 个答案:

答案 0 :(得分:16)

因为在你的setter中,你正在调用 setter ,它会进入setter,然后调用...... setter ......和......

 set
 {    
    albums = value;       // < --- This line calls itself again.. 
    Session["albums"] = albums;
 }

您需要做的只是使用Session [“albums”]作为值的持久存储...您不需要私有字段 - 这只是创建值的冗余副本。完全消除它,然后放......

private List<Albums> Albums
{    
    get    
    {        
         if (Session["albums"] != null)
              return (List<Albums>) Session["albums"];        
         else            
            return (Session["albums"] = AlbumCollection.GetAlbums());    
    }    
    set    
    {    
        Session["albums"] = value;    
    }
}

在某些没有持久存储的情况下,公共属性只有一个私有成员支持字段是完全可以接受的。

有关C#属性的更多信息,请查看MSDN tutorial

答案 1 :(得分:11)

你正在重新分配财产本身。

在您的情况下,您只使用会话。

所以这应该没问题

private List<Albums> albums
{
    get
    {
        if (Session["albums"] == null)
            Session["albums"] = AlbumCollection.GetAlbums();
        return (List<Albums>)Session["albums"];
    }
    set
    {
        Session["albums"] = value;
    }
}

答案 2 :(得分:5)

问题在于这一行:

albums = value;

您递归地将属性设置为value,它将一次又一次地调用setter,直到它堆栈溢出。这行代码没有意义。摆脱它。

我想有一种错误的误解,即某个属性需要绑定到某个字段或其他东西。不是。一个属性本身只是几个不相关的方法,不需要彼此或字段有任何特定的关系。当您检索属性值时,只需调用其get方法并使用返回值,并在设置其值时,使用相应的set参数调用其value方法。您不需要以某种方式“更改”setter中的属性值。当您更改get将要返回的值时,将自动强制执行语义,以便下次调用get时,它将返回您已更改的Session["..."]

答案 3 :(得分:3)

这一行引起了你的问题,因为它最终以无限循环递归调用你的getter:

albums = value;

答案 4 :(得分:3)

经过一番快速搜索,这应该可以帮到你:Why does this cause a StackOverFlow error?

答案 5 :(得分:1)

你的setter在第一个例子中递归调用自己。你的第二个解决了这个问题。

是的,你可以做到。

答案 6 :(得分:1)

你是对的,在第一个例子中,你递归地无限次地调用专辑设置器,因此堆栈溢出。 (C#属性和方法应始终以大写字母btw开头)。

在第二个例子中,你可以简单地使用:

Session["albums"] = value;

如果你愿意的话。

答案 7 :(得分:1)

你是对的,问题是当你在引用这个setter / getter的第一个代码块中使用“albums”时。因此,当您在setter中执行albums = value时,您将再次以递归方式调用setter。

在内部,编译器将访问器转换为函数,它可以帮助您自己查看错误:

private List<Albums> albums
{
    set
    {
    albums = value;
    Session["albums"] = albums;
    }
}

编译后,变为:

private void set_albums(List<Albums> value)
{
    set_albums(value);
    Session["albums"] = albums;
}

答案 8 :(得分:0)

两次调用Session [“Albums”]是一个常见的错误。会话索引是一项相对昂贵的操作,涉及字典查找。

private List<Albums> Albums {    
get
{        
     object stored = Session["albums"];
     if (stored != null)
          return (List<Albums>) stored;
     else
     {      
        var newValue = AlbumCollection.GetAlbums();
        Albums = newValue;
        return newValue;
     }
}    
set    
{    
    Session["albums"] = value;
}}