我在“设置”属性下面的行为是什么?

时间:2018-08-08 12:59:26

标签: c#

我试图创建简单的事件,下面是代码块,但无法正常工作。当我尝试调试时,一旦创建Point对象,它就会在“ Set”属性上抛出“ StackOverFlowException”(甚至在我们分配值p.x = 10之前)。我做错了什么?

using System;

namespace Workshop
{

    public class Point
    {
        public int x
        {
            get { return x; }
            set
            {
                x = value;
                onPointeChanged();
            }
        }

        public int y
        {
            get { return y; }
            set
            {
                y = value;
                onPointeChanged();
            }
        }

        public event EventHandler pointchanged;

        private void onPointeChanged()
        {
            if (pointchanged != null)
                pointchanged(this, EventArgs.Empty);
        }

    }

    public class Program
    {

        public static void Main(String[] args)
        {
            Point p = new Point();
            p.pointchanged += HandleEvent;
            p.x = 10;
        }

        public static void HandleEvent(object obj, EventArgs sender)
        {
            Console.WriteLine("Event Raised");
        }

    }
}

谢谢

3 个答案:

答案 0 :(得分:4)

您将无限期地调用set方法,直到耗尽堆栈内存为止。你在做什么

x = value;

您是在调用x属性的setter,而后者又是x = value,所以它会自称,依此类推,以此类推,直到永远。

要解决此问题,请引入一个字段:

private int x;

public int X
{
    get => x;
    set
    {
         x = value;
         OnPointChanged();
    }
}

这是使用get和/或set后的自定义逻辑创建属性的正确方法。如果您没有OnPointChanged()逻辑,就可以这样做

public int X { get; set; }

这将为您生成以下代码:

private int x;
public int X { get => x; set => x = value; }

答案 1 :(得分:3)

问题是您要在属性的自身设置器中为其分配值:

public int x
{
    get { return x; }
    set
    {
        x = value; // <-- see you are assigning `value` to your `x` property.
        onPointeChanged();
    }
}

这将无限循环。您需要创建一个后备字段:

private int _myField;

public int BetterNameThanX
{
    get { return _myField; }
    set
    {
        _myField = value;
        onPointeChanged();
    }
}

答案 2 :(得分:1)

您已经定义了属性,并且返回了每个自己的属性,这些属性导致在getset范围上的递归。尝试定义私有attributes并通过属性公开它:

public class Point
{
    private int _x;
    public int x
    {
        get { return _x; }
        set
        {
            _x = value;
            onPointeChanged();
        }
    }

    private int _y;
    public int y
    {
        get { return _y; }
        set
        {
            _y = value;
            onPointeChanged();
        }
    }

    public event EventHandler pointchanged;

    private void onPointeChanged()
    {
        if (pointchanged != null)
            pointchanged(this, EventArgs.Empty);
    }

}