21

Suppose I have the following disposable class and example code to run it:

public class DisposableInt : IDisposable
{
    private int? _Value;

    public int? MyInt
    {
        get { return _Value; }
        set { _Value = value; }
    }

    public DisposableInt(int InitialValue)
    {
        _Value = InitialValue;
    }

    public void Dispose()
    {
        _Value = null;
    }
}

public class TestAnInt
{
    private void AddOne(ref DisposableInt IntVal)
    {
        IntVal.MyInt++;
    }

    public void TestIt()
    {
        DisposableInt TheInt;
        using (TheInt = new DisposableInt(1))
        {
            Console.WriteLine(String.Format("Int Value: {0}", TheInt.MyInt));
            AddOne(ref TheInt);
            Console.WriteLine(String.Format("Int Value + 1: {0}", TheInt.MyInt));
        }
    }
}

Calling new TestAnInt().TestIt() runs just fine. However, if I change TestIt() so that DisposableInt is declared inside of the using statement like so:

    public void TestIt()
    {
        // DisposableInt TheInt;
        using (DisposableInt TheInt = new DisposableInt(1))
        {
            Console.WriteLine(String.Format("Int Value: {0}", TheInt.MyInt));
            AddOne(ref TheInt);
            Console.WriteLine(String.Format("Int Value + 1: {0}", TheInt.MyInt));
        }
    }

I get the following compiler error:

Cannot pass 'TheInt' as a ref or out argument because it is a 'using variable'

Why is this? What is different, other than the class goes out of scope and to the garbage collector once the using statement is finished?

(and yeah, I know my disposable class example is quite silly, I'm just trying to keep matters simple)

Irinotecan
  • 567
  • 1
  • 6
  • 12
  • 2
    Just a tip: conventionally, Java variables are named with the first letter lower-case and camelCased on word boundaries. Your `TheInt` variable should be renamed `theInt`. It helps the readability of your code to others if you follow conventions. – Jesse Webb Jul 24 '12 at 17:56
  • Your example code doesn't even need ref at all, since you are not trying to change the reference. – Chris Dunaway Jul 24 '12 at 22:31

1 Answers1

32

Why is this?

Variables declared in using statements are read-only; out and ref parameters aren't. So you can do this:

DisposableInt theInt = new DisposableInt(1);
using (theInt)
{
    AddOne(ref theInt);
}

... but fundamentally you're not using the fact that it's a ref parameter anyway...

It's possible that you've misunderstood what ref really means. It would be a good idea to read my article on parameter passing to make sure you really understand.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    Thank you! The missing link for me was that a 'using variable' is read-only. I think I see why: Because then I could say theInt = new DisposableInt(2) *inside* the using statement mucking things up royally! So even my "working" sample code is bad practice, I guess. – Irinotecan Jul 24 '12 at 18:20