Adam Lerman
Adam Lerman

Reputation: 3399

Why does Property Set throw StackOverflow exception?

I know java and would normally put in getter/setter methods. I am interested in doing it in C# with the following code, but it throws a StackOverflow exception. What am I doing wrong?

Calling Code

c.firstName = "a";

Property Code

public String firstName;
{
    get
    {
        return firstName;
    }
    set
    {
        firstName = value;
    }
}

Upvotes: 68

Views: 51715

Answers (3)

Dorin Baba
Dorin Baba

Reputation: 1728

StackOverflowExeption is inevitable in your snippet, and that's why.

To understand that, we have to know what properties are and why we use them. Basically, a property is a set o methods, it's not a field. Via 'Property' we mean the collection of set method (which sets the value of something), and get method (which returns the value of something).

Properties offer us a level of flexibility when it comes to assigning values to private fields with the help of methods mentioned above.

Your code does not work because you're overflowing the stack by calling the get method again and again, it's like a recursive function without any exit condition (when we try to get FirstName's value, the property calls it's get method, which returns itsels, and again get is called, and again get is called, again, again, again and your stack fills up with this stuff).

If you have a private field in your class, you can expose it using a property around that filed, and we can add additional processing for get and set method, here is an example: Say we want to get the ascii code of a digit (0 to 9), we can use a property for this (This is not the best example, it's just to illustrate some use of properties):

// this is the private field that we do not want to expose (aka to make
// it accessible for everyone
private int digit;

// But we want somehow to allow users of our class to interact 
// with the digit field, so we create a property.
// Note: fields' name start with lowercase, properties' name with Uppercase
public int Digit
{
   get 
   {
       // this is the method that gets calls whenever the user calls Digit,
       // Example: Console.WriteLine(object.Digit);

       // let's add here the logic of getting digit's ascii code
       return Char.Parse(digit.ToString());
   }

   set
   {
       // this method gets called when someone assigns a value for Digit
       // Example: Digit = 3;
     
       // here we can add the validation logic ( 0 <= value <=9)
       if(value < 0 || value > 9)
          throw new Exception("Please provide a number between 0 and 9");
    
       digit = value;
    }
}  

We used the Digit property to convert the digit to ASCII when it is accessed by someone, and to validate the value that one tries to assign to our digit field.

In your case, you can just write the FirstName property like this:

public string FirstName{  get; set; }

Under the hood, this line will be treated the same as:

private string firstName;
public string FirstName
{
   get { return firstName; }
   set { firstName= value }
}

More detailed on why the stack is overflown.

There are many languages that don't have properties like C# does, so people just add separate get & set methods. Having this model, it's much more easier to spot where the overflow occurs. Let's imagine there are not properties in C#, so we create a private field and two methods - one for setting, other for getting private field's value.

private string firstName;

public string GetFirstName()
{
    return firstName;
}

public void SetFirstName(string value)
{
   firstName = value;
}

Now he have a setter and getter, which are not wrapped in a property. To see where the overflow occurs in the question's example, let's adapt it to our new environment where we don't have properties;

public string GetFirstName()
{
   return GetFirstName();
}

public void SetFirstName(string value)
{
   GetFirstName() = value; 
}

This is literally what your code does. There is no private field to play with, to the property plays with itself ^^

When we write this:

object.SetFirstName("Rick Astley");

We go into SetFirstName method, which calls GetFirstName(), and voala, dead end. Treat the '=>' as 'calls':

SetFirstName("Rick Astley") => GetFirstName() => GetFirstName() => ...

Upvotes: 0

Michael Haren
Michael Haren

Reputation: 108236

You are setting the property name inside your property--not the field name. This would work better:

private string m_firstName;

public String firstName;
{
    get
    {
        return m_firstName;
    }
    set
    {
        m_firstName = value;
    }
}

Upvotes: 15

Greg Beech
Greg Beech

Reputation: 136577

It's because you're recursively calling the property - in the set you are setting the property again, which continues ad infinitum until you blow the stack.

You need a private backing field to hold the value, e.g.

private string firstName;

public string FirstName
{
    get
    {
        return this.firstName;
    }
    set
    {
        this.firstName = value;
    }
}

Alternatively, if you're using C# 3.0, you could use an auto-property, which creates a hidden backing field for you, e.g.

public string FirstName { get; set; }

Upvotes: 131

Related Questions