Passing Property values by reference

I was wondering how well properties were integrated into C#.  For example, C# lets you use += with the properties.   It's easy enough to convert:
    MyProperty += 4
    MyProperty = MyProperty + 4

However, C# won't let you pass a property in as a ref parameter.  For example:
    void PassIntByRef(ref int x)
    PassIntByRef(ref MyProperty);
  <-- this is illegal in C#.

At first I thought C# was being lame. Afterall, why couldn't it do something like:
    int __temp = MyProperty;
    PassIntByRef(ref __temp); 
    MyProperty = __temp;

Then it hit me that was not correct behavior. Consider this example:

    int a = 5;
    PassPairByRef(ref a, ref a);

    void PassPairByRef(ref int x1, ref int x2) {
        x1++;         // 1) caller's reference to x1 (variable a) is immediately changed
        // since x1 and x2 are the same ref, x2 is changed too!
        // 2) So both x1 and x2 are now updated to 6

The naive codegen proposal above obviously would break down here. PassPairByRef  would need some pretty fancy codegen to handle a reference- property. The only way I can imagine is that it would effectively need a pair of delegates to the get_MyProperty  and set_MyProperty methods. That would codegen to something like:       

    delegate int Getter();
    delegate void Setter(int val);
    void PassPairByRef(Getter x1_get, Setter x1_set, Getter x2_get, Setter x2_set)
        x1_set(x1_get() + 1);
And then the callsite would look something like (this is pseudo-code):
            new Getter(get_MyProperty), new Setter(set_MyProperty), // ref for x1
            new Getter(get_MyProperty), new Setter(set_MyProperty)); // ref for x2

Since this is obviously less efficient than passing normal (non-property) values by-ref, the codegen would probably want two separate versions of the method: one for the normal case and one for properties.

Some random closing thoughts:
1. A higher-level language could certainly do this underneath the covers (and I bet out of the many .NET languages today, there are ones already that do).
2. I think in an alternative universe, the CLR also could have handled this too and allowed languages to directly pass properties as by-ref parameters. The CLR's JITter could handled the codegen above and even managing both versions of the target method; and it could even have an optimized way of indirectly calling get and set property methods.

Comments (16)

  1. Eric W says:

    This may just be my personal experience, but isn’t the case of passing two copies of the same property to a method a very rare special case?  Would it not make more sense to codegen property parameters to the first example you gave above and present a complier error flag if a property is used more than once in the same parameter list?

  2. Robert says:

    VB.Net allows passing a Property as a ByRef parameter:


    public Class Foo

    shared sub Main

    Dim x as new Foo(0)

    System.Console.WriteLine(x.TestProperty) ‘ outputs "0"

    x.ByRefMethod(x.TestProperty, x.TestProperty)

    System.Console.WriteLine(x.TestProperty) ‘ outputs "1"

    end sub

    public sub New(initialValue as Integer)

    Me._testProperty = initialValue

    End Sub

    Public Sub ByRefMethod(ByRef a as Integer, ByRef b as Integer)

    a += 1

    b -= 1

    End Sub

    private _testProperty as Integer

    public property TestProperty as Integer


    return me._testProperty

    End Get

    Set(value as Integer)

    me._testProperty = value

    End Set

    End Property

    end Class


    Reflector reverses the IL of Sub Main into the following code:


    Public Shared Sub Main()

         Dim foo1 As New Foo


         Dim foo2 As Foo = foo1

         Dim num1 As Integer = foo2.TestProperty

         Dim foo3 As Foo = foo1

         Dim num2 As Integer = foo3.TestProperty

         foo1.ByRefMethod(num1, num2) ‘ !operating on two different variables

         foo3.TestProperty = num2

         foo2.TestProperty = num1 ‘ overwrites the update from the previous line


    End Sub


    Notice that the generated code passes two different integer variables in and writes the new values back to the property in reverse order.

  3. Eric W – it’s true my case is a little contrived; I did that too simplify it.

    You could construct more complex real-looking cases that expose the same problem. For example, what happens when you pass a ref parameter as a ref-parameter to another function. In that case, it could be reasonably to have 1 function taking in 2 ref-parameters that actually point to the same object.

    Another case is if instead of passing the same property twice; you passed MyProperty to a by-ref on thread A; and then checked its result on thread B after Thread A modified it but before thread A returned.

  4. Adam M. says:

    Your example with PassIntByRef() looked fine, and I don’t see how it would break.

    How does PassPairByRef() come into play? Properties only have a single return value…

    Can you give an example when PassPairByRef(ref T a, ref T b) would be needed?

  5. Adam M. says:

    For instance, if I did the following:

    void PassPairByRef(ref int a, ref int b)

    { a++;


    obj.Property = 5;

    PassPairByRef(ref obj.Property, ref obj.Property);

    (oh, i see it now. 🙂

  6. Adam –

    PassIntByRef() would succeed. If it was a more complex function, say something that looked at the reference parameter halfway through, then it would fail.

  7. Alois Kraus says:

    Hi Mike,
    I have thought about the idea and came up with a little helper which lets you (nearly) pass properties by reference:


     Alois Kraus

  8. Alois – looks nice. That’s a pretty unorthodox way to use reflection.  😉

    I notice you wrote it in C#; I wonder if you write it directly in IL if you can dance around some C# issues (such as being able to get a delegate directly to the get method).

  9. Alois Kraus says:

    Thanks, Mike for calling my method unorthodox ;-). I have looked with IL DASM at my code and properties. The metadata ".method public hidebysig specialname" looks promising to get my hands on the right function signature. But unfortunately I do not know enough IL to emulate the Reflection mechanism with IL code. It looks easy in the decompiled code to add a call to a property but during runtime I am not sure.

  10. Grant Parks says:

    When the method that was called with a ByRef of a property returns, it actually calls the setter of that property – even when the method did nothing to the property.  This had some big side effects for me – when properties are calculated values (where getters/setters have more meaningful code than the usual worthless "prop = Value" and "Return prop")

  11. Grant – good point!

    That would be even worse for properties that don’t round-trip (

  12. Be wary of "required" properties that must be explicitly set correctly in order for the object to function

  13. LA.NET [EN] says:

    Properties are strange beasts…in fact, when you access a property, you&#39;re really calling a method

Skip to main content