2009-12-18 3 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; 
    } 
} 

Для решения выше, я изменил имя свойства и добавил еще одну переменные для хранения стоимость имущества, которое решен вопрос 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; 
    } 
} 

Кроме того, я делаю сеттер правильно, присваивая значение, а затем присваивающей Session [ «альбомы»] значение в альбомах? Могу ли я только что сделать, Session ["albums"] = значение вместо этого?

ответ

11

Вы были переназначены самим имуществом.

В вашем случае вы используете сеанс.

Так что это должно быть хорошо

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

ОК, я думал, что смогу это сделать, но я боялся, что сделаю это неправильно, если раньше не делал альбомы = значение. Благодарю. – Xaisoft

5

Проблема с этой линией:

albums = value; 

Вы рекурсивно устанавливая свойство value который будет вызывать сеттер снова и снова, пока она не stackoverflows , В этой строке кода нет смысла. Просто избавься от этого.

Я предполагаю, что существует ложное заблуждение, что свойство должно быть привязано к полю или чему-то еще. Это не. Само по себе свойство - это всего лишь пара несвязанных методов, которые не требуют какого-либо конкретного отношения друг к другу или к полю. Когда вы извлекаете значение свойства, вы просто вызываете его метод get и используете возвращаемое значение, и когда вы устанавливаете его значение, вы вызываете его метод set с соответствующим аргументом value. Вам не нужно каким-либо образом «изменять» значение свойства в сеттер. Семантика автоматически применяется при изменении значения, которое get собирается вернуть, поэтому в следующий раз, когда вы вызовете get, он вернет Session["..."], который вы уже изменили.

1

Ваш сеттер вызывает себя рекурсивно в первом примере. Ваша вторая проблема исправлена.

Да, вы могли бы это сделать.

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

В некоторых случаях, когда вы не имеете постоянный магазин, это вполне приемлемо для публичной собственности иметь только личное поле член подкладочный.

Для получения дополнительной информации о свойствах C# в целом, ознакомьтесь с MSDN tutorial.

+0

Итак, если у меня только что был сеанс ["albums"] = value, было бы хорошо? – Xaisoft

+0

Смотрите мой второй пример ... –

+0

@Xaisoft: Да, это все, что вам нужно. –

3

Эта строка вызывает проблему, потому что ветры звонит геттер рекурсивно в бесконечном цикле:

albums = value; 
1

Вы правильно, в первом примере, вы рекурсивно Назвав альбом инкубационных бесконечное число раз, следовательно, переполнение стека. (C# Свойства и методы всегда должны начинаться с буквы верхнего регистра btw).

Во втором примере вы могли бы просто использовать:

Session["albums"] = value; 

, если вы хотите.

1

Вы правы, проблема в том, что когда вы используете «альбомы» в первом блоке кода, вы имеете в виду этот сеттер/получатель. Таким образом, когда вы делаете albums = value в сеттере, вы рекурсивно вызываете сеттер снова.

Внутренне компилятор преобразует аксессор в функцию, и это может помочь вам увидеть свою ошибку, делая это самостоятельно:

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

При компиляции, становится:

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

Общепринятой ошибкой является вызов сеанса ["Альбомы"] дважды. Индексирование сеансов является относительно дорогостоящей операцией, включающей поиск словаря.

+0

Я вижу, что вы говорите, вместо доступа к сеансу в инструкции if, и когда я возвращаю список альбомов, сначала сохраните его в объекте и проверьте объект? Верный? – Xaisoft