【问题标题】:C# stack overflowC# 堆栈溢出
【发布时间】:2009-07-29 09:21:02
【问题描述】:

我正在尝试找出为什么会出现堆栈溢出异常。我正在为学校作业创建一个简单的纸牌游戏,当我克隆卡片以返回它们时,我得到了堆栈溢出异常。

所以我得到了这个卡片类:

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”类型的未处理异常

【问题讨论】:

  • 卡片是否需要可变,即它们是否具有可以更改的状态?如果没有,那么您可以只拥有一组可以在不同集合中重复使用的不可变卡片。无需克隆。
  • 另请参阅有关 ICloneable 的讨论:stackoverflow.com/questions/699210/…
  • 在阅读了这个问题的标题后,我认为这属于元... ;-)

标签: c# stack-overflow icloneable


【解决方案1】:

你是在给自己打电话:

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

但这使您对克隆过程的控制较少。

【讨论】:

  • +1,很好的答案。每当使用 MemberwiseClone() 时,请不要忘记它只创建一个浅拷贝,即如果类字段是引用类型,则复制引用,而不是引用对象。
【解决方案2】:

我倾向于将 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();
    }
}

OrganisationLazyLoadPrefs 还在整个层次结构中实现 ICloneable 等等。

希望这会有所帮助, 干杯, 特里

【讨论】:

  • 虽然刚刚看到来自@peterchen 的评论,但必须更详细地了解这一点 - 热衷于尽可能遵循最佳实践。
猜你喜欢
  • 2012-12-20
  • 2011-03-02
  • 2014-01-17
  • 1970-01-01
  • 1970-01-01
  • 2019-05-18
  • 2014-12-28
  • 1970-01-01
相关资源
最近更新 更多