Вопрос

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

Итак, я получил этот класс карт:

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 и так далее и тому подобное по всей иерархии.

Надеюсь, это поможет, ура, Терри

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top