Home > Software design >  Beginner: Is there an elegant way to update all copies of an instance?
Beginner: Is there an elegant way to update all copies of an instance?

Time:05-04

The following code doesn't update the copy of a inside the array.

int a = null;    
int[] numbers = new int[1];
numbers[0] = a;
a = 5; // 5
Console.WriteLine(numbers[0]); // null

Got a programming task requiring to set-up a structure of locations linked by portals between them which isn't possible by just listing the required connections. I'll get references to null that stay null even if I fill an entity later in the code.

Looking for keywords or techniques which might solve my issue.

CodePudding user response:

You could have reference types instead of value types inside array, therefore updating the value of the inner object will also affect the array.

var tab = new MyClass[1];
var obj = new MyClass(5);
tab[0] = obj;
Console.WriteLine(tab[0].Value);  // 5

tab[0].Value = 10;
Console.WriteLine(tab[0].Value);  // 10

obj.Value = 15;
Console.WriteLine(tab[0].Value);  // 15

public class MyClass
{
    public MyClass(int value)
    {
        Value = value;
    }
    public int Value { get; set; }
}

CodePudding user response:

integers is a value type, as such the actual value is copied. So there is never any 'instance' in your example code, only copies of the value.

You should probably wrap your value in a class, since classes are a reference type to get your desired behavior. This might be useful when you need to share some mutable between multiple components. You can also add an event that is raised whenever the value is changed to let any component that needs the value know that it might need to update something. For example:

    public class MyChangeable<T>
    {
        private T value;
        public MyChangeable(T value) => this.value = value;
        public T Value
        {
            get => value;
            set
            {
                this.value = value;
                OnChanged(this, value);
            }
        }
        public event EventHandler<T> OnChanged;
    }

There is also ref return and ref locals that could do something like your example, but this is mostly intended to get better performance by avoiding copies of large structs, it is not as useful if you want to share values between components.

CodePudding user response:

Arrays are reference types

var a = new int[1];    
var numbers = new [] { a };

a[0] = 5;
Console.WriteLine(numbers[0][0]); 

You just have to remember that you're one level deeper than you wanted to be/you need to stick a [0] on everything you wouldn't have stuck it on before. It's a bit of a hack, and I'd probably make a class for it like other answers recommend, but stuffing a value type in an array of size 1 can be a useful technique to quickly get reference type behavior out of a value type

CodePudding user response:

ref locals may help you in your task, even if they have strict limitations due to the lifetime of the involved objects, so they could be not applicable as a general solution.

A small example based on your question can be as follows:

int[] array = new int[1];
ref int elem = ref array[0];
elem = 5;
Console.WriteLine(array[0]); // 5

This works not only with value types (including nullable types) but also with reference types.

  • Related