StackOverflow Exception from get and set

2020-02-14 05:18发布

问题:

I have the following code:

namespace QuantStrats
{
    class Program
    {
        static void Main(string[] args)
        {
            string FilePath = "C:\\Users\\files\\DJ.csv";
            StreamReader streamReader = new StreamReader(FilePath);
            string line;
            List<Data> Data = new List<Data>();     

            while ((line = streamReader.ReadLine()) != null)
            {
                Data Tick = new Data();
                string [] values = line.Split(',');
                Tick.SetFields(values[1], values[2]);
                Data.Add(Tick);
            }

            for (int ii = 0; ii < Data.Count; ii++)
            {
                Data TickDataValues = new Data();
                TickDataValues = Data[ii];             
                Console.Write("TIME :" + TickDataValues.time + " Price : " + TickDataValues.price +  Environment.NewLine);
            }

            Console.ReadLine();
        }
    }

    class Data
    {
        public DateTime time
        {
            get { return this.time; }
            set
            {
                this.time = value;                
            }
        }

        public double price
        {
            get { return this.price; }
            set
            {
                this.price = value;                
            }
        }

        public void SetFields(string dateTimeValue, string PriceValue)
        {
            try
            {
                this.time = Convert.ToDateTime(dateTimeValue);
            }
            catch
            {
                Console.WriteLine("DateTimeFailed " + dateTimeValue + Environment.NewLine);
            }

            try
            {
                this.price = Convert.ToDouble(PriceValue);
            }
            catch
            {
                Console.WriteLine("PriceFailed " + PriceValue + Environment.NewLine);
            }
        }
    }
}

But I get a stack overflow exception.

I know it is because I am not doing my get and sets correctly and am entering an infinite loop, but I cannot see why exactly this is happening?

回答1:

public DateTime time
{
    get { return this.time; }
    set
    {
        this.time = value;                
    }
}

you aren't using backing fields, but setting the property itself from within the property setter.

You can fix this by using 1) an auto property

public DateTime Time { get; set; }

or 2) a backing field

private DateTime _time;
public Datetime Time 
{
    get { return _time; }
    set { _time = value; }
} 

they both equate to the same code.

For an explanation, when you get time in your code:

get { return this.time; } 

it has to retrieve the value of time to return. It does that by calling the get on time, which has to get retrieve the value of time, etc.



回答2:

I cannot see why exactly this is happening?

    public double price
    {
        get { return this.price; }
        set
        {
            this.price = value;                
        }
    }

When you "get" price, the getter for price is called, which calls the getter for price, which calls the getter for price, which...

Just use auto-implement properties if you don't want to mess with a backing field:

    public DateTime Time {get; set;}
    public double Price {get; set;}

Some other observations:

  1. The standard convention for property names is to start them with a capital letter, which is why I changed your properties to Time and Price in my examples.

  2. You may want to consider using decimal for a property like Price if you do any floating-point math, since double has some slight imprecision when representing decimal numbers like 1.1. decimal will store the number exacly without any loss of precision.

  3. Just writing to the console in a catch block seems incorrect. You are basically ignoring the error (from a logic flow sense). Rather than accepting strings in the class and parsing them, I would do the validation in the calling code and making sure the inputs are valid before passing them to the class.



回答3:

Properties getters and setters are really just getXXX and setXXX methods (that's how they are compiled). Because you set the property from the property itself, it is if you were recurring endlessly on a method.

public DateTime time()
{
    return time();
}

As stated by other answers, you can use backing fields or auto-implemented properties.



标签: c# get set