通过引用传递的参数何时更新?

时间:2010-06-30 22:03:49

标签: c# reference parameter-passing

假设我有这样的方法:

public void MyCoolMethod(ref bool scannerEnabled)
{
    try
    {
        CallDangerousMethod();


    } 
    catch (FormatException exp)
    {
        try
        {
            //Disable scanner before validation.
            scannerEnabled = false;

            if (exp.Message == "FormatException")
            {
                MessageBox.Show(exp.Message);
            }
        }
        finally
        {
            //Enable scanner after validation.
            scannerEnabled = true;
        }
    }

它的用法如下:

    MyCoolMethod(ref MyScannerEnabledVar);

扫描仪可以随时在单独的线程上触发。我们的想法是,如果我们处理异常,就不要让它。

我的问题是,当设置scannerEnabled时,对MyCoolMethod的调用是否会更新MyScannerEnabledVar,还是在方法退出时更新它?

注意:我没有编写此代码,我只是想安全地重构它。

4 个答案:

答案 0 :(得分:5)

您可以将ref视为为变量创建别名。并不是你传递的变量是“通过引用传递”,而是参数和参数是相同的变量,只有两个不同的名称。所以更新一个会立即更新另一个,因为这里实际上并没有两件事。

正如SLaks所说,VB中存在使用copy-in-copy-out语义的情况。如果我没记错的话,还有一些罕见且模糊的情况,其中表达式树可以编译成复制拷贝的代码,但我不记得细节。

如果此代码旨在更新变量以便在另一个线程上读取,则变量“立即”更新的事实会产生误导。请记住,在多个线程上,如果读取和写入不是易失性,则可以观察到读取和写入相对于彼此向前和向后移动。如果打算将变量用作跨线程通信机制,则为此目的使用实际 Designed 的对象, safe 。使用某种等待句柄或互斥或其他。

答案 1 :(得分:4)

它会在实时更新,因为它是在方法内部分配的。

当您通过引用传递参数时,运行时传递(等效于)指向您引用的字段或变量的指针。当方法分配给参数时,它直接分配给引用所指向的内容。

顺便说一句,请注意,这在VB中并不总是如此。

答案 2 :(得分:1)

是的,在方法中设置变量时将设置它。也许最好是返回true或false,无论是否启用扫描程序而不是将其作为参考文件传递

答案 3 :(得分:1)

这种情况不仅仅需要简单的重构。您发布的代码将受竞争条件的限制。简单的解决方案是锁定不安全的方法,从而迫使线程跳线。就这样,由于这段代码,应用程序中肯定会出现一些错误,但如果不了解更多关于您的需求和实现的话,就不可能说出它们究竟是什么。我建议你谨慎行事,互斥/锁定是一个简单的解决方案,但可能会对性能产生很大影响。如果这是您关注的问题,那么您应该检查一个更好的线程安全解决方案。