Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/295.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# &引用;e、 取消“;正式闭幕式_C#_.net_Events_Formclosing - Fatal编程技术网

C# &引用;e、 取消“;正式闭幕式

C# &引用;e、 取消“;正式闭幕式,c#,.net,events,formclosing,C#,.net,Events,Formclosing,使用FormClosing事件时,为什么代码e.Cancel=true工作,但新建CancelEventArgs()。Cancel=true不工作 private void Form1_FormClosing(object sender, FormClosingEventArgs e) { e.Cancel = true; new CancelEventArgs().Cancel = true; } 我认为代码完全按照它所说的去做;缺少的是对它的字面解读 将新值指定给e.Ca

使用
FormClosing
事件时,为什么代码
e.Cancel=true工作,但
新建CancelEventArgs()。Cancel=true不工作

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    e.Cancel = true;

    new CancelEventArgs().Cancel = true;
}

我认为代码完全按照它所说的去做;缺少的是对它的字面解读

将新值指定给
e.Cancel
时,您正在修改作为函数参数提供的
e
。事件处理程序函数完成后,此
FormClosingEventArgs
实例(包括从事件处理程序中对其所做的任何更改)将可用于调用事件处理程序的任何代码。在本例中,几乎可以肯定这是由Microsoft编写的Winforms代码

另一方面,当您在该事件处理程序中创建一个类型为
FormClosingEventArgs
的新实例并对其执行某些操作时,无法将该信息提供给调用者;你需要一些明确的东西。由于调用方正在查看事件处理程序完成后传入的参数的值,因此您需要以某种方式将调用方看到的
e
的内容替换为新创建的实例。在其他情况下,这样的结果可以作为返回值提供

一般来说,
newt()
的结果对于某些类型
T
,是类型
T
的一个实例。因此,您可以像处理类型为
T
的非空变量一样处理表达式
new T()
的结果。在您的特定情况下,您正在为类型
T
上的属性赋值(具体地说,就是这样创建的该类型的实例)。(有一种特殊情况是构造函数失败,但我们暂时不谈这个问题;对于简单类型,这几乎意味着您陷入了困境,您的程序在任何情况下都不可能继续运行。)

这里重要的是,如果不将表达式
new t()
本身的结果赋给任何位置,则在语句完成后,新创建的实例将被丢弃(从技术上讲,将变得不可访问)。然后在稍后的某个时刻,.NET垃圾收集器开始工作,并实际回收分配的内存。它实际上与在一个函数中分配一个变量、从另一个函数调用该函数并尝试访问从第二个函数分配的变量没有什么不同,只是这里只涉及一个函数


在事件处理程序中执行类似于第二行代码的操作是非常不寻常的,但如果调用构造函数会产生一些副作用,例如触发延迟加载,则原则上是有效的。

事件是由Winforms管道代码引发的。它可以看到自定义事件处理程序想要更改默认行为的唯一方法是通过
e
对象。创建新的CancelEventArgs对象没有管道可以检测到的副作用

还有一些问题,事件是为了外部代码的利益而产生的,让它知道发生了什么,并给它一个改变行为的选项。这里没有外部代码,事件处理程序实际上是引发事件的同一类的一部分。换句话说,表单正在倾听自己的事件。有一种更好的方法来处理这个问题,您可以重写引发事件的方法。像这样:

    protected override void OnFormClosing(FormClosingEventArgs e) {
        e.Cancel = true;
        base.OnFormClosing(e);
    }

现在外部代码可以覆盖默认行为,在OnXxxx方法运行后引发事件。您可以选择,如果您不想让外部代码覆盖该行为,只需交换这两条语句。

这段代码肯定可以工作,只需检查它

protected override void OnFormClosing(FormClosingEventArgs e)
        {            
            base.OnFormClosing(e);
            if (PreClosingConfirmation() == System.Windows.Forms.DialogResult.Yes)
            {
                Dispose(true);
                Application.Exit();
            }
            else
            {
                e.Cancel = true;
            }
        }

        private DialogResult PreClosingConfirmation()
        {
            DialogResult res = System.Windows.Forms.MessageBox.Show(" Do you want to quit?          ", "Quit...", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            return res;
        }

快乐编码

这是因为
CancelEventArgs
是传递给代码中事件处理程序的对象引用。幕后代码使用
CancelEventArgs
对象引发
FormClosing
,所有事件处理程序都接收相同的对象。所有处理程序轮到后,幕后代码检查它发送的
CancelEventArgs
对象,查看其
Cancel
属性是否设置为
true
。如果是,它什么也不做,
FormClose
事件链停止。如果
Cancel
false
CancelEventArgs
默认值),意味着未将其设置为
Cancel
事件链,则幕后代码继续执行,然后引发
FormClosed
事件

你可以在网站上阅读更多

表单中
所有的-ing事件后面通常都有-ed事件。ing事件通常具有
CancelEventArgs
,可以将其
Cancel
属性设置为
true
,以阻止ed事件发生