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吗?
这是一个无休止的循环:
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 Name
或Name = 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
表示属性。您需要定义一个后备字段并使用它。
如果FriendlyName
是null
,则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.
}