一个相当简单的问题(我认为),但我似乎没有看到答案。我知道有些值是通过值传递的(比如int和long),而其他值是通过引用传递的(比如字符串),当你将它们传递给函数时。
在我的程序中,我使用后台工作程序,因此当我们在后台执行长时间的过程时,GUI不会锁定。我需要将数据从另一个文件传递回UI线程,所以我一直在使用事件。现在我需要将一个字符串数组列表发送回GUI线程来处理,我担心它将如何处理。基本上,在工作线程中,我有一个循环,它将填充列表,通过事件处理程序将其发送回GUI,然后清除它,以便它可以在下一次循环中填充它并重新开始。
我担心当我这样做时,如果列表是通过引用传递的,那么在UI线程上,我会认为它会在读取中间被清除,因为工作线程仍将在后台清除它。在这种情况下,传递将是更可取的,我可以找到强制它的方法(复制到某个持有者数组或添加互斥或类似的东西),但我认为知道事件参数是否通过传递是很好的一般的引用或值,或者它与方法是否相同,并且它会在通常传递参数时传递它们?
答案 0 :(得分:21)
我知道有些值是通过值传递的(比如int和long),而其他值是通过引用传递的(比如字符串),当你将它们传递给函数时。
不。默认情况下,所有内容都按值传递 - 但是当您使用引用类型时,“所有内容”都是引用。该引用按值传递。那个不与通过引用传递相同。有关详细信息,请参阅my article on parameter passing。
事件参数完全相同 - 假设相应的委托不使用out
或ref
参数,任何引用都按值传递。
编辑:所以要解决你的顾虑:是的,如果你的事件参数是可变的并且你要在不同的线程上行动,你应该首先创建一个副本......或者,传递现有的引用,然后创建工作线程中的新(空)列表。
答案 1 :(得分:4)
默认情况下,参数本身按值传递。但是,根据其类型,它们可以是您正在使用的实际值的值或引用。
请注意,这与通常称为通过引用传递的内容不同,因为实际传递给参数的值已被复制(即按值传递 )。但是,效果类似,如果您更改方法中的引用对象,则更改将在方法之外(在您调用方法的代码中)可见。
现在,当通过值传递时,事件参数没有什么特别之处;是复制值还是只复制它们的引用完全取决于它们的类型。所以,正如你所说,int
和long
参数(以及更多,任何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之类的值返回给调用者。