2009-12-18 257 views
0

這是導致一個StackOverFlow錯誤,我有一個想法爲什麼,但我想了解一些更詳細的原因,是我的解決方案,它應該被處理。好吧,首先第一件事情,下面的代碼會導致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; 
    } 
} 

要解決上述,我改變了屬性的名稱,並添加另一個變量來保存

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; 
    } 
} 

而且,我在做二傳手正確,指定的值,然後分配會議[「專輯」在相冊中的價值:它解決了問題計算器的財產價值?我可以剛剛完成嗎,Session [「albums」] = value呢?

回答

11

您正在重新分配屬性本身。

就你而言,你只是使用Session。

所以這應該是罰款

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

好吧,我想我可以做到這一點,但我害怕如果我沒有先做專輯=值,我會做錯。謝謝。 – Xaisoft 2009-12-18 16:23:19

5

問題是這一行:

albums = value; 

您是遞歸設置屬性爲value,將一次次給二傳手,直到它stackoverflows 。這行代碼沒有意義。只是擺脫它。

我想有一個錯誤的觀念認爲一個屬性需要綁定到某個字段或某個東西。不是。一個屬性本身就是一對不相關的方法,它們之間不需要有任何特定的相互關係或與某個領域的關係。當您檢索屬性值時,只需調用它的get方法並使用返回值,並在設置其值時,使用適當的value參數調用其set方法。你不需要以某種方式「改變」setter中的屬性值。當您改變get將要返回的值時,語義會自動執行,所以下次打電話給get時,它將返回您已經更改的Session["..."]

1

你的setter在第一個例子中遞歸調用自己。你的第二個修復了這一點。

是的,你可以做到。

16

因爲在你的二傳手,你在呼喚......在二傳手,都到了二傳,並調用...的二傳手 ......還有......

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;  
    } 
} 

在某些情況下,你沒有持久性存儲,這是完全可以接受的公共屬性,使其具有隻是一個私有成員支持字段。請參閱MSDN tutorial

+0

所以,如果我只有Session [「albums」] = value,那會好嗎? – Xaisoft 2009-12-18 16:21:40

+0

查看我的第二個例子... – 2009-12-18 16:22:26

+0

@ Xaisoft:是的,這是您所需要的。 – 2009-12-18 16:23:20

3

此行是造成你的問題,因爲它纏遞歸調用你的getter無限循環:

albums = value; 
1

你是正確的,在第一個例子中,你是遞歸調用專輯二傳手無限次,因此堆棧溢出。 (C#屬性和方法應該始終以大寫字母btw開頭)。

在第二個例子中,你可以簡單地使用:

Session["albums"] = value; 

,如果你想。

1

你是對的,問題是當你在第一個代碼塊中使用「相冊」時,你指的是這個setter/getter。因此,當你在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; 
} 
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; 
}} 
+0

我看到你在說什麼,而不是在if語句中訪問會話,並且當我返回相冊列表時,首先將其存儲在對象中並檢查該對象?正確? – Xaisoft 2009-12-18 18:23:37

相關問題