1

This is the working class:

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

Then I try and modify the Name getter and 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;
        }
    }
}

On my computer this compiles fine, but the server seems to crash when it runs. (First version works fine). My colleague compiled it on his machine and it threw a "Stack overflow error" apparently, but he's not around for me to get specifics on that right now.

Am I applying the getter correctly here?

8 Answers 8

11

This is an endless loop:

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

The setter will call itself repeatedly until you get the Stack overflow exception.

usually you have a backing variable, so it ends up like this

private string name;
public string Name { 
  get {
    if (null != FriendlyName)
      return FriendlyName;
    else
      return name;
    }
  set {
    name = value;
  }
}
Sign up to request clarification or add additional context in comments.

Comments

5

Your set is referencing the property itself, and your get is referencing the property itself, both of these will cause a potentially endless loop leading to a StackOverflowException (no more stack space to push the current call into). You need to use a backing field:

private string _name;

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

It looks as though you tried to turn an auto-property into a manual one. Auto-properties (public string Name { get; set; }) work because the compiler will create the backing field itself.

As a learning exercise, if you step through with the debugger and step into return Name or Name = value you will see first hand the code going back into the property you are already in.

Comments

2

This is much better.

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

Comments

1

One of your properties gets and sets itself, see:

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

Comments

1

You have a getter for Name, that calls the property Name, which will call the getter for Name, etc. You need a private field to back the property, and you need to access that backing field in your getter instead.

Comments

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

Name in the get/set refers to the property. You will need to define a backing field and use that.

Comments

0

If FriendlyName is null then the Name getter attempts to get the value from the Name getter - i.e. it loops. This is what causes the stack overflow.

Comments

0

No you should use a backing field. The error is in the else

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.