Stackoverflow错误C#与getter和setter

时间:2011-08-17 12:15:02

标签: c# asp.net getter-setter getter

这是工人阶级:

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

在我的计算机上编译很好,但服务器运行时似乎崩溃了。 (第一个版本工作正常)。我的同事在他的机器上对它进行了编译,并且它显然出现了“堆栈溢出错误”,但他现在还没有找到具体内容。

我在这里正确使用了吸气剂吗?

8 个答案:

答案 0 :(得分:11)

这是一个无限循环:

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

答案 1 :(得分:5)

你的集合引用了属性本身,你的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,您将看到第一手代码返回到属性中已经在。

答案 2 :(得分:2)

这要好得多。

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

答案 3 :(得分:1)

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

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

答案 4 :(得分:1)

你有一个名字的getter,它调用属性Name,它将调用Name的getter等。你需要一个私有字段来支持该属性,你需要访问getter中的那个支持字段。 / p>

答案 5 :(得分:0)

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

set指的是该属性。您需要定义一个支持字段并使用它。

答案 6 :(得分:0)

如果FriendlyNamenull,则Name获取者会尝试从Name获取者获取值 - 即它会循环播放。这是导致堆栈溢出的原因。

答案 7 :(得分:0)

不,您应该使用支持字段。错误发生在else

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