事件参数是通过C#中的引用还是值传递的?

时间:2012-08-03 17:34:26

标签: c# .net events event-handling reference-type

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

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

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

4 个答案:

答案 0 :(得分:21)

  

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

不。默认情况下,所有内容都按值传递 - 但是当您使用引用类型时,“所有内容”都是引用。该引用按值传递。那个与通过引用传递相同。有关详细信息,请参阅my article on parameter passing

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

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

答案 1 :(得分:4)

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

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

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

请注意,在C#中也可以通过引用传递真正的,但这需要ref keyword

答案 2 :(得分: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
}

答案 3 :(得分:1)

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

事件参数通常是一个类(通常继承自EventArgs),通常用于将诸如eventArgs.DoCancel之类的值返回给调用者。