In C#, it may seem like assigning values to class fields by reference can be achieved using the ref parameter modifier. However, this technique fails to preserve the reference when assigning to a field.
Consider the following code snippet:
public class X { public X() { string example = "X"; new Y(ref example); new Z(ref example); System.Diagnostics.Debug.WriteLine(example); } } public class Y { public Y(ref string example) { example += " (Updated By Y)"; } } public class Z { private string _Example; public Z(ref string example) { this._Example = example; this._Example += " (Updated By Z)"; } } var x = new X();
The expected output is to see both updates applied to the string: "X (Updated By Y) (Updated By Z)" but the actual output is only "X (Updated By Y)". This raises the question of how to maintain the reference when assigning to a field.
The limitation stems from the fact that C# does not allow fields of ref type. This constraint forces the choice between either disallowing ref fields entirely or allowing unsafe fields that could potentially lead to crashes. Additionally, using the temporary storage pool for local variables (the stack) would conflict with accessing values that may no longer exist after the method completes.
To avoid these issues, C# prohibits ref fields and recommends using getter and setter methods instead:
sealed class Ref<T> { private readonly Func<T> getter; private readonly Action<T> setter; public Ref(Func<T> getter, Action<T> setter) { this.getter = getter; this.setter = setter; } public T Value { get { return getter(); } set { setter(value); } } } ... Ref<int> x; void M() { int y = 123; x = new Ref<int>(() => y, z => { y = z; }); x.Value = 456; Console.WriteLine(y); // 456 -- setting x.Value changes y. }
Using this approach, x effectively becomes an object that has the ability to get and set the value of y, even though y is stored on the garbage collected heap.
While C# does not directly support ref returning methods and ref parameters, this feature was implemented in C# 7. However, it remains a limitation that ref types cannot be used as fields.
The above is the detailed content of Why Doesn't Passing Values to Class Fields by Reference Work in C# and How Can I Achieve Similar Behavior?. For more information, please follow other related articles on the PHP Chinese website!