Переполнение стека C#
-
20-09-2019 - |
Вопрос
Я пытаюсь выяснить, почему я получаю исключение переполнения стека.Я создаю простую карточную игру для школьного задания, и когда я клонирую карты, чтобы вернуть их, я получаю исключение переполнения стека.
Итак, я получил этот класс карт:
public class Card : ICloneable
{
....
#region ICloneable Members
public object Clone()
{
return this.Clone(); // <--- here is the error thrown when the first card is to be cloned
}
#endregion
}
и у меня есть класс под названием Hand
который затем клонирует карты:
internal class Hand
{
internal List<Card> GetCards()
{
return m_Cards.CloneList<Card>(); // m_Cards is a List with card objects
}
}
Наконец, я получил метод расширения для List
:
public static List<T> CloneList<T>(this List<T> listToClone) where T : ICloneable
{
return listToClone.Select(item => (T)item.Clone()).ToList();
}
Ошибка выдается в классе карты (метод IClonable),
В CardLibrary.dll произошло необработанное исключение типа «System.StackOverflowException».
Решение
Вы звоните себе:
public object Clone()
{
return this.Clone();
}
Это приводит к бесконечной рекурсии.
Ваш метод Clone() должен скопировать все свойства/поля в новый объект:
public object Clone()
{
Card newCard = new Card();
newCard.X = this.X;
// ...
return newCard;
}
или вы можете использовать MemberwiseClone()
public object Clone()
{
return MemberwiseClone();
}
Но это дает вам меньше контроля над процессом клонирования.
Другие советы
Я обычно использовал MemberwiseClone() для простых данных, а затем реализовал ICloneable во всей иерархии элементов, которые мне нужно было клонировать, поэтому:
public class CRMLazyLoadPrefs : ICloneable
{
public bool Core { get; set; }
public bool Events { get; set; }
public bool SubCategories { get; set; }
public OrganisationLazyLoadPrefs { get; set; }
public object Clone()
{
CRMLazyLoadPrefs _prefs = new CRMLazyLoadPrefs();
// firstly, shallow copy the booleans
_prefs = (CRMLazyLoadPrefs)this.MemberwiseClone();
// then deep copy the other bits
_prefs.Organisation = (OrganisationLazyLoadPrefs)this.Organisation.Clone();
}
}
Где OrganizationLazyLoadPrefs также реализует ICloneable и так далее и тому подобное по всей иерархии.
Надеюсь, это поможет, ура, Терри