为什么修改用户控件代码后构建应用程序时会导致整个 Visual Studio 崩溃?

3
在此链接中,接受答案的原始用户控件代码为:如何在UserControl Paint事件中动画显示点? 我对其进行了一些更改,并添加了保存更改选项。因此,我添加了一些用户设置属性,其中之一是SaveState:
[DefaultValue(false)]
        public bool SaveState
        {
            get => saveState;
            set
            {
                if (value)
                {
                    saveState = value;
                }

                Properties.Settings.Default.SaveState = value;
                Properties.Settings.Default.Save();
            }
        }

而在构造函数中:

public LoadingLabel()
        {
            InitializeComponent();

            SaveState = Properties.Settings.Default.SaveState;
        }

问题在于当我添加另一行以更新SaveState时,整个应用程序和Visual Studio都会崩溃,Visual Studio重新启动,而控件没有被拖到Form1设计器中。崩溃发生在我进行更改后,将控件拖到Form1设计器时。

这是我所做的更改:

[DefaultValue(false)]
        public bool SaveState
        {
            get => saveState;
            set
            {
                if (value)
                {
                    saveState = value;
                    SaveState = value;
                }

我添加了这行代码:
SaveState = value;

因为它正在更新saveState并且运作良好,但是在视觉上我看不到SaveState属性的变化:
SaveState被设置为true,但是当我将其更改为false时,只有当我将控件从设计器中删除并重新拖动它时才会看到它变为false。

SaveState

不确定为什么在尝试更新SaveState本身时会崩溃。


3
在构造函数中,你设置了后备字段而不是属性,所以 saveState = Properties.Settings.Default.SaveState;--移除 if (value),无论valuetrue还是false,你都需要设置后备字段。你可以检查新的value是否与存储的值不同,如果相同,则什么也不做,因为重复做同样的事情是没有用的--在这里:SaveState = value;,你创建了一个递归调用到setter,它会使整个东西崩溃。在属性的setter中,你-再次-设置后备字段,而不是属性。 - Jimi
不确定您的意思。如果属性设置正确,当然您会在PropertyGrid中看到值的变化。如果您的意思是您有两个相同控件的实例,并且您在其中一个中更改了属性值,则另一个不会反映出来,这是因为您没有订阅Properties.Settings.Default的PropertyChanged事件,该事件触发时应设置支持字段。当您这样做时,在表单设计器中从一个实例切换到另一个实例会导致PropertyGrid再次读取属性值,因此在所有实例中更新属性。 - Jimi
@Jimi表现不错。如果我想稍微改变SaveState的行为怎么办?现在,当我需要将saveState更改为true时,必须先更改其他属性以使其保存更改。但是,如果例如我首先更改了interval属性,然后再将SaveState更改为true,这样它就会进行保存,然后如果我再次拖动控件并将SaveState更改回false,则它将带有保存的更改。 - jhon last
@Jimi,SaveState 就像一个开关,如果是 true 则保存,false 则不保存。现在它的行为是我需要先将其更改为 true 然后再更改属性。但我希望如果我更改了属性值,然后将 SaveState 更改为 true,那么也会保存。 - jhon last
@jimi 保持现有的SaveState行为,同时添加“按钮”行为。当设置为true时,SaveState将保存所有已经进行的更改以及我之后所做的更改;当设置为false时,则不保存任何更改。 - jhon last
显示剩余3条评论
1个回答

2
当你编写代码时,
SaveState = value;

你调用了 setter 方法。

当你在 setter 的代码中这样做时,会导致无限递归 - 你在 setter 中对 SaveState 进行赋值,它又调用了 setter,然后又对 SaveState 进行赋值,又调用了 setter,又对 SaveState 进行赋值,又调用了 setter,如此循环下去,导致 IDE 崩溃。

故事的寓意是:永远不要在 setter 内部对属性进行赋值;始终对备份字段进行赋值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接