getter和setter出现堆栈溢出错误C#

本文关键字:栈溢出 错误 堆栈 setter getter | 更新日期: 2023-09-27 18:05:56

这是工作类:

namespace Lite
{
    public class Spec
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string FriendlyName { get; set; }
        public int CategoryID { get; set; }
        public int Width { get; set; }
        public int Height { get; set; }
        public string UOM { get; set; }
        public int Pagination { get; set; }
        public int ColoursFront { get; set; }
        public int ColoursBack { get; set; }
        public string Material { get; set; }
        public int GSM { get; set; }
        public string GSMUOM { get; set; }
        public bool Seal { get; set; }
        public Spec(int ID)
        {
            using (CrystalCommon.MainContext db = new CrystalCommon.MainContext())
            {
                var q = (from c in db.tblSpecifications where c.id == ID select c).SingleOrDefault();
                if (q != null)
                    loadByRec(q);
            }
        }
        public Spec(CrystalCommon.tblSpecification Rec)
        {
            loadByRec(Rec);
        }
        public void loadByRec(CrystalCommon.tblSpecification Rec)
        {
            this.ID = Rec.id;
            this.Name = Rec.Title;
            this.Width = Convert.ToInt32(Rec.FinishedSizeW.Value);
            this.Height = Convert.ToInt32(Rec.FinishedSizeL.Value);
            this.UOM = Rec.FlatSizeUOM;
            this.Pagination = Rec.TxtPagination.Value;
            this.ColoursFront = Convert.ToInt32(Rec.TxtColsF.Value);
            this.ColoursBack = Convert.ToInt32(Rec.TxtColsB.Value);
            this.Material = Rec.TxtMaterial;
            this.GSM = Rec.TxtGSM.Value;
            this.GSMUOM = Rec.txtGsmUnit;
            this.Seal = Rec.TxtSeal.Value == 1;
        }
        public string displayDimensions()
        {
            return Width + " x " + Height + " " + UOM;
        }
    }
}

然后我尝试修改Name getter和setter:

namespace Lite
{
    public class Spec
    {
        public int ID { get; set; }
        // User friendly name if available otherwise fall back on spec name
        public string Name { get {
            if (null != FriendlyName)
                return FriendlyName;
            else
                return Name;
            }
            set
            {
                Name = value;
            }
        }
        public string FriendlyName { get; set; }
        public int CategoryID { get; set; }
        public int Width { get; set; }
        public int Height { get; set; }
        public string UOM { get; set; }
        public int Pagination { get; set; }
        public int ColoursFront { get; set; }
        public int ColoursBack { get; set; }
        public string Material { get; set; }
        public int GSM { get; set; }
        public string GSMUOM { get; set; }
        public bool Seal { get; set; }
        public Spec(int ID)
        {
            using (CrystalCommon.MainContext db = new CrystalCommon.MainContext())
            {
                var q = (from c in db.tblSpecifications where c.id == ID select c).SingleOrDefault();
                if (q != null)
                    loadByRec(q);
            }
        }
        public Spec(CrystalCommon.tblSpecification Rec)
        {
            loadByRec(Rec);
        }
        public void loadByRec(CrystalCommon.tblSpecification Rec)
        {
            this.ID = Rec.id;
            this.Name = Rec.Title;
            this.Width = Convert.ToInt32(Rec.FinishedSizeW.Value);
            this.Height = Convert.ToInt32(Rec.FinishedSizeL.Value);
            this.UOM = Rec.FlatSizeUOM;
            this.Pagination = Rec.TxtPagination.Value;
            this.ColoursFront = Convert.ToInt32(Rec.TxtColsF.Value);
            this.ColoursBack = Convert.ToInt32(Rec.TxtColsB.Value);
            this.Material = Rec.TxtMaterial;
            this.GSM = Rec.TxtGSM.Value;
            this.GSMUOM = Rec.txtGsmUnit;
            this.Seal = Rec.TxtSeal.Value == 1;
        }
        public string displayDimensions()
        {
            return Width + " x " + Height + " " + UOM;
        }
    }
}

在我的计算机上,这编译得很好,但服务器在运行时似乎会崩溃。(第一个版本运行良好(。我的同事在他的机器上编译了它,它显然抛出了一个"堆栈溢出错误",但他现在不在我身边,无法了解具体情况。

我在这里正确地应用了getter吗?

getter和setter出现堆栈溢出错误C#

这是一个无休止的循环:

public string Name { get {
  ...
  set
  {
    Name = value;
  }
}

setter将重复调用自己,直到您得到Stack溢出异常。

通常你有一个后备变量,所以它最终像这个

private string name;
public string Name { 
  get {
    if (null != FriendlyName)
      return FriendlyName;
    else
      return name;
    }
  set {
    name = value;
  }
}

您的set正在引用属性本身,而get正在引用属性自身,这两者都将导致潜在的无休止循环,导致StackOverflowException(没有更多的堆栈空间可将当前调用推入(。你需要使用一个后备字段:

private string _name;
public string Name 
{ 
    get 
    {
        if (null != FriendlyName)
            return FriendlyName;
        else
            return _name;
    }
    set
    {
        _name = value;
    }
}

看起来好像您试图将自动属性转换为手动属性。自动属性(public string Name { get; set; }(之所以有效,是因为编译器将自己创建支持字段。

作为一个学习练习,如果您逐步使用调试器并逐步进入return NameName = value,您将看到代码直接返回到您已经所在的属性中。

这要好得多。

string _name = "";
public string Name
{
    get { return FriendlyName ?? _name; }
    set { _name = value; }
}

您的一个属性获取并设置自己,请参阅:

   public string Name
   {
       get {
        if (null != FriendlyName)
            return FriendlyName;
        else
            return Name; //<-- StackOverflow
        }
        set
        {
            Name = value; //<-- StackOverflow
        }
    }

您有一个用于Name的getter,它调用属性Name,它将调用用于Name等的getter。您需要一个私有字段来支持该属性,而您需要在getter中访问该支持字段。

public string Name { get {
            if (null != FriendlyName)
                return FriendlyName;
            else
                return Name;
            }
            set
            {
                Name = value;
            }
        }

get/set中的Name表示属性。您需要定义一个后备字段并使用它。

如果FriendlyNamenull,则Name getter尝试从Name getter获取值,即循环。这就是导致堆栈溢出的原因。

不,您应该使用后备字段。错误在else

        public string Name { get {
        if (null != FriendlyName)
            return FriendlyName;
        else
            return Name;//error, you're calling the property getter again.
        }