Compiler warning CS0728

I'm getting a compiler warning with the following code:


foo = someOperation();
lock( foo )
{
...
internalmethod(ref foo );
...
}

The warning is:

file.cs (3,1): warning CS0728: Possibly incorrect assignment to local 'foo' which is the argument to a using or lock statement. The Dispose call or unlocking will happen on the original value of the local.

Has the compiler not recognised that foo is a ref parameter? Is this a bug/problem or I should I be doing something different? Thanks in advance!

I'm compiling using VS.NET 2005 Beta 2. VS.NET 2003 did not generate this warning.

[890 byte] By [adamhearn] at [2008-2-6]
# 1

Although I have never encountered this, it seems to be saying that although 'foo' is being passed by reference to internalmethod (which could change it's value), the Monitor.Exit() will be called on the original value of 'foo' and not the changed value.

DavidM.Kean at 2007-9-7 > top of Msdn Tech,Visual C#,Visual C# Language...
# 2
Sorry for the late follow-up! I fully agree with your assessment.

The purpose of the InternalMethod is to update a set of members on the object received, not change the object reference itself. It would be helpful if the C# compiler allowed me to decorate the argument with 'const' (or similar) that made my intentions clear thus enforcing correct usage during compilation.

As noted previously, there was no similar warning under VS.NET 2003.

adamhearn at 2007-9-8 > top of Msdn Tech,Visual C#,Visual C# Language...
# 3

If are not going to change the object reference itself, then why are you using 'ref'? 'ref' causes a method to refer to the same variable that was passed in, so in the above situation internalmethod could change the object reference and hence the warning.

Most situations do not require ref.

DavidM.Kean at 2007-9-8 > top of Msdn Tech,Visual C#,Visual C# Language...
# 4

As I see it the warning refers to the fact that you can (rather strangely I find) update what the ref argument actually 'points' to. Take this example code:

static void Main( string[] args )
{
TestObj local = new TestObj();
local.MyProperty = 123;
lock( local )
{
Console.WriteLine( "Created object. Hash code: " + local.GetHashCode() );
IntM(
ref local );
Console.WriteLine( "Post IntM call. Hash code: " + local.GetHashCode() );
}
}

static void IntM( ref TestObj arg )
{
Console.WriteLine( "IntM called. Hash code: " + arg.GetHashCode() );
arg =
new TestObj();
Console.WriteLine( "IntM returning Hash code: " + arg.GetHashCode() );
}

This is what I beleive the warning is referring to. However in my scenario I would never expect to change the object reference itself but only to update the members of the object. The code I'm working with would be less efficient if I could not pass the object by reference so that some of the members can be updated.

adamhearn at 2007-9-8 > top of Msdn Tech,Visual C#,Visual C# Language...
# 5

That's not totally true. When you pass a reference type (ie class) to a method, you are only copying the reference to the class, not the entire object.

In .NET it is considered bad practice to use 'ref'. You find little, if any performance benefit by using it.

In fact, I just did a quick test, using the following test harness, and found the ref method to be actually slower. This is pretty rough and results could be different for you.

Ref - 31.9921260
Normal - 31.4162730


static class Program
{
[STAThread]
static void Main()
{
MyClass instance = new MyClass();

// Avoid timing the JIT
DoSomething(ref instance);
DoSomething(instance);

Stopwatch watch = Stopwatch.StartNew();

for (int i = 0; i < int.MaxValue; i++)
{
DoSomething(ref instance);
}

watch.Stop();
Console.WriteLine(watch.Elapsed.ToString());

watch = Stopwatch.StartNew();

for (int i = 0; i < int.MaxValue; i++)
{
DoSomething(instance);
}

Console.WriteLine(watch.Elapsed.ToString());
}


public class MyClass
{
string field1;
string field2;
}

public static void DoSomething(ref MyClass instance)
{

}

public static void DoSomething(MyClass instance)
{

}


DavidM.Kean at 2007-9-8 > top of Msdn Tech,Visual C#,Visual C# Language...
# 6
Yes, I see I'd somehow glossed over the fact that the 'value' of a reference type is actually the reference of the instance and thus the InternalMethod would be able to update the incoming object's properties! Therefore you're correct in stating that I have no need for the 'ref' when passing a reference type.
adamhearn at 2007-9-8 > top of Msdn Tech,Visual C#,Visual C# Language...