views:

90

answers:

4

Suppose I have a method like this:

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;
        }
    }

And it is used like this:

    MyCoolMethod(ref MyScannerEnabledVar);

The scanner can fire at any time on a separate thread. The idea is to not let it if we are handling an exception.

The question I have is, does the call to MyCoolMethod update MyScannerEnabledVar when scannerEnabled is set or does it update it when the method exits?

Note: I did not write this code, I am just trying to refactor it safely.

+4  A: 

It gets updated live, as it is assigned inside the method.

When you pass a parameter by reference, the runtime passes (an equivalent to) a pointer to the field or variable that you referenced. When the method assigns to the parameter, it assigns directly to whatever the reference is pointing to.

Note, by the way, that this is not always true in VB.

SLaks
Yep it gets changed the millisecond you do a var = somenewvalue;
Justin
+1  A: 

Yes, it will be set when the variable is set within the method. Perhaps it would be best to return true or false whether the scanner is enabled rather than pass it in as a ref arg

aqwert
+5  A: 

You can think of a ref as making an alias to a variable. It's not that the variable you pass is "passed by reference", it's that the parameter and the argument are the same variable, just with two different names. So updating one immediately updates the other, because there aren't actually two things here in the first place.

As SLaks notes, there are situations in VB that use copy-in-copy-out semantics. There are also, if I recall correctly, rare and obscure situations in which expression trees may be compiled into code that does copy-in-copy-out, but I do not recall the details.

If this code is intended to update the variable for reading on another thread, the fact that the variable is "immediately" updated is misleading. Remember, on multiple threads, reads and writes can be observed to move forwards and backwards in time with respect to each other if the reads and writes are not volatile. If the intention is to use the variable as a cross-thread communications mechanism them use an object actually designed for that purpose which is safe for that purpose. Use some sort of wait handle or mutex or whatever.

Eric Lippert
+1  A: 

The situation calls for more than a simple refactor. The code you posted will be subject to race conditions. The easy solution is to lock the unsafe method, thereby forcing threads to hop in line. The way it is, there's bound to be some bug(s) in the application due to this code, but its impossible to say what exactly they are without knowing a lot more about your requirements and implementation. I recommend you proceed with caution, a mutex/lock is an easy fix, but may have a great impact on performance. If this is a concern for you, then you all should review a better thread safe solution.

P.Brian.Mackey