15

一个相当简单的问题(我认为),但我似乎还没有看到答案。我知道有些值是通过值传递的(如 int 和 long),而其他值是通过引用传递的(如字符串),当您将它们传递给函数时。

在我的程序中,我使用后台工作程序,这样当我们在后台进行长时间的处理时,GUI 就不会锁定。我需要将数据从另一个文件传回 UI 线程,所以我一直在使用事件。现在我需要将字符串数组列表发送回 GUI 线程以在那里处理,我担心它会如何处理。基本上,在工作线程中,我有一个循环来填充列表,通过事件处理程序将其发送回 GUI,然后清除它,以便它可以在下一次通过循环时填充它并重新开始。

我担心当我这样做时,如果列表是通过引用传递的,那么在 UI 线程上,我会认为它会在读取中被清除,因为工作线程仍会在后台清除它。在这种情况下,通过会更好,我可以找到强制它的方法(复制到某个持有者数组或添加互斥锁或类似的东西),但我认为最好知道事件参数是否通过一般的引用或值,还是只是与方法相同,它会将它们作为通常传递的参数传递?

4

4 回答 4

22

我知道有些值是通过值传递的(如 int 和 long),而其他值是通过引用传递的(如字符串),当您将它们传递给函数时。

没有。默认情况下,所有内容都是按值传递的——但是当您使用引用类型时,“所有内容”都是引用。该引用是按值传递的。这通过引用传递不同。有关详细信息,请参阅我关于参数传递的文章。

事件参数完全相同——任何引用都是按值传递的,假设相应的委托不使用outref参数。

编辑:所以为了解决您的问题:是的,如果您的事件参数是可变的并且您将在不同的线程上采取行动,您应该首先创建一个副本......或者,传递现有的引用,然后创建一个新的 (空)在您的工作线程中列出。

于 2012-08-03T17:37:09.330 回答
4

默认情况下,参数本身是按值传递的。但是,根据它们的类型,它们可以是值或对您正在使用的实际值的引用。

请注意,这与通常所说的按引用传递不同,因为实际传递给参数的值是被复制的(即按值传递)。但是,效果是相似的,如果您在方法内更改引用的对象,更改也将在方法外(在您调用该方法的代码中)可见。

现在,当按值传递时,事件参数没有什么特别之处;是复制值还是仅复制它们的引用完全取决于它们的类型。因此,正如您所说,int参数long(以及更多,任何struct类型)是值类型,而其他类似string(以及任何类实例)是引用类型。

请注意,在 C# 中也可以通过引用进行真正的传递,但这需要ref关键字.

于 2012-08-03T17:37:11.697 回答
3

在标准事件模式中,传入了两个引用:

 void FormClosing(object sender, FormClosingEventArgs e) { ... }

这两个引用是“按值”传递的,例如使用sender = null在处理方法之外没有任何影响。

但是您可以轻松地传回一个值:

void FormClosing(object sender, FormClosingEventArgs e)
{
    ...
    e.Cancel = true;  // this will pass back to the caller
}
于 2012-08-03T17:43:20.133 回答
1

事件参数根据参数的类型事件处理程序委托的签名in、 out 或 ref )传递 - 如果是类,则传递引用的副本,如果是结构,则值的副本被传递(假设签名没有指定 out 或 ref)。

事件参数通常是一个类(通常从EventArgs继承)并且通常用于向调用者返回诸如 eventArgs.DoCancel 之类的值。

于 2012-08-03T17:38:15.397 回答