Search code examples
c#stack-overflow

Stack overflow error in C# - but how to fix it?


I've run into a really interesting runtime bug which generates a rogue stack overflow.

I've defined a structure as follows:

public enum EnumDataType { Raspberry, Orange, Pear, Apple };

public class DataRequest
{
    public long DataSize 
    { 
        get { return 0; } 
        set { DataSize = value; } 
    }

    public EnumDataType DataType  
    { 
        get { return EnumDataType.Apple; } 
        set { DataType = value; } 
    }
}

The following lines work perfectly:

DataRequest request = new DataRequest();
request.DataSize = 60;

However, when I step over the following line in code, it generates a stack overflow:

request.DataType = EnumDataType.Raspberry;

Of course, I can fix it by removing the defaults, or using auto get/set, but I need it to be both readable and writable, and return a default - any ideas?


Solution

  • As others have said, the stack overflow occurs because your property setter is just calling itself. It may be simpler to understand if you think of it as a method:

    // This obviously recurses until it blows up
    public void SetDataType(long value)
    {
        SetDataType(value);
    }
    

    As I understand it, you're trying to create normal properties but with a default value, right?

    In that case, you need backing variables which are set by the setters - and the getters should return those variables, too. It's the variables which should get default values:

    private long dataSize = 0;
    public long DataSize {
      get { return dataSize; }
      set { dataSize = value; }
    }
    
    private EnumDataType dataType = EnumDataType.Apple;
    public EnumDataType DataType { 
      get { return dataType; }
      set { dataType = value; }
    }
    

    Alternatively, use automatic properties but set the defaults in your constructor:

    public long DataSize { get; set; }
    public EnumDataType DataType { get; set; }
    
    public DataRequest()
    {
        DataSize = 0; // Not really required; default anyway
        DataType = EnumDataType.Apple;
    }