Home > database >  C# - Assign an object's field as reference to another object's field (like a pointer)
C# - Assign an object's field as reference to another object's field (like a pointer)

Time:03-04

I have two objects, from same class type. They both have a property (and its private field). Conditionally, I would like to assign this property/field as a reference to the same property/field of another instance of the same class.

It's important to note that my requirement is to read the referenced field. Write to it would be a bonus, not a problem, and not necessary.

I would like to know if it would be possible to use a ref field, and do some logic inside the property getter.

Also, I know there has been some questions about this here on StackOverflow (here, here, here, here), but they are all pretty old (so the idea of duplicate does not seem to apply here).
Now we are on C# 10.0, and a lot of different ref capabilities had been implemented, like ref locals. I tried to use some of them, but I failed. Hope someone with more knowledge could help me to see a way to do it.

So, is it possible, without using a wrapper to link one instance's property to another?? (which is my current approach, detailed below)


More details:

That's my class (actually it's a huge simplification of it):

public class Person
{
    private string _fullName;
    public string FullName { get => _fullName; set => _fullName = value; }
}

And, let's say I have 3 instances of this class. Now, if I try to assign the value of one property to another, the value is simply copied (as expected. I already am fairly aware why it is):

var person01 = new Person() { FullName = "Steve" };
var person02 = new Person() { FullName = "Mr. S" };
var person03 = new Person() { FullName = "Mister Steve" };

person02.FullName = person01.FullName;
// person02.FullName is "Steve"
person01.FullName = "Mr. Steve Jobs";
// person01.FullName is "Mr. Steve Jobs"
// person02.FullName is "Steve" because the value was only copied.

I UNDERSTAND WHY IT IS. But I want to know if there is some elegant way to do this:

ref person02.FullName = ref person01.FullName;  // not allowed
ref person03.FullName = ref person02.FullName;  // not allowed

person01.FullName = "Mr. Steve Jobs";
// person01.FullName is "Mr. Steve Jobs"
// person02.FullName is "Mr. Steve Jobs"
// person03.FullName is "Mr. Steve Jobs"

So the idea is assign a field as a reference to another field of another object. I believe that through a Property it's not possible, since it's actually a "method" to get and set the private field.

So i did this, it works, but it's not pretty:

public class Person
{
    private string _fullName;
    public string FullName
    {
        get => (FullName_Reference == null ? _fullName : FullName_Reference.FullName);
        set => _fullName = value;
    }
    public Person FullName_Reference { get; set; }

    public Person()
    {
        _fullName = "";
        FullName_Reference = null;
    }
}

var person01 = new Person() { FullName = "Steve" };
var person02 = new Person() { FullName = "Mr. S" };
var person03 = new Person() { FullName = "Mister Steve" };

person02.FullName_Reference = person01;
person03.FullName_Reference = person02;

person01.FullName = "Mr. Steve Jobs";
// person01.FullName is "Mr. Steve Jobs"
// person02.FullName is "Mr. Steve Jobs"
// person03.FullName is "Mr. Steve Jobs"

Seeking for a more elegant way to do it, I even tried to expose the private field _fullName (through a method returning a ref), but i was unable to set the private field (also through a method) of the other object as a reference to the reference object returned previously. It always just copy its value.

CodePudding user response:

I'm not familiar with all of the new features of C# 10.0, but you can achieve the desired behaviour by treating the name as an object in it's own right, and referencing the Name object in each of your Person instances. i.e. just treat it as a composition

public class Name
{
    public string FullName { get; set; }

    public Name(string fullName)
    {
        FullName = fullName;
    }
}

public class Person
{
    public Name Name { get; set; }

    public string FullName => Name.FullName;

    public Person(Name name)
    {
        Name = name;
    }
}

var person01 = new Person(new Name("Steve"));
var person02 = new Person(new Name("Mr. S"));
var person03 = new Person(new Name("Mister Steve"));

person02.Name = person01.Name;
person03.Name = person02.Name;

person01.Name.FullName = "Mr. Steve Jobs";
// person01.FullName is "Mr. Steve Jobs"
// person02.FullName is "Mr. Steve Jobs"
// person03.FullName is "Mr. Steve Jobs"

CodePudding user response:

In my opinion the easiest way to achieve what you want is to use a Func<string> to retrieve reference values:

class Person
{
    private Func<string> _fullName;
    public string FullName { get => _fullName(); set => _fullName = () => value; }

    public void SetFullNameRef(Func<string> value)
    {
        _fullName = value;
    }
}


static void Main(string[] args)
{
    var person01 = new Person() { FullName = "Steve" };
    var person02 = new Person() { FullName = "Mr. S" };
    var person03 = new Person() { FullName = "Mister Steve" };

    person02.SetFullNameRef(() => person01.FullName);
    person03.SetFullNameRef(() => person02.FullName);

    person01.FullName = "Mr. Steve Jobs";

    Console.WriteLine(person01.FullName); // Mr. Steve Jobs
    Console.WriteLine(person02.FullName); // Mr. Steve Jobs
    Console.WriteLine(person03.FullName); // Mr. Steve Jobs
}

Or write it like that:

class Person
{
    private Func<string> _fullName;
    public string FullName { get => _fullName(); set => _fullName = () => value; }
    public Func<string> RefFullName { get => () => _fullName(); set => _fullName = () => value(); }
}


static void Main(string[] args)
{
    var person01 = new Person() { FullName = "Steve" };
    var person02 = new Person() { FullName = "Mr. S" };
    var person03 = new Person() { FullName = "Mister Steve" };

    person02.RefFullName = person01.RefFullName;
    person03.RefFullName = person02.RefFullName;

    person01.FullName = "Mr. Steve Jobs";

    Console.WriteLine(person01.FullName); // Mr. Steve Jobs
    Console.WriteLine(person02.FullName); // Mr. Steve Jobs
    Console.WriteLine(person03.FullName); // Mr. Steve Jobs
}
  • Related