C# - 将对象的字段分配为对另一个对象字段的引用(如指针)

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

我有两个对象,来自相同的 class 类型。他们都有一个 属性 (及其私有字段)。 有条件地,我想将此 property/field 分配为对相同 class.

的另一个实例的相同 property/field 的引用

请务必注意,我的要求是阅读引用的字段。给它写信是加分项,不是问题,也不是必须的。

我想知道是否可以使用 ref 字段,并在 属性 getter.

中做一些逻辑

此外,我知道 Whosebug 上有一些关于此的问题 (here, here, here, here),但它们都已经很老了(因此重复的想法似乎不适用于此处)。
现在我们使用的是 C# 10.0,并且已经实现了许多不同的 ref 功能,例如 ref locals。我尝试使用其中的一些,但我失败了。希望有知识的人能帮我看看有什么办法。

那么,是否可以不使用包装器将一个实例的 属性 link 包装到另一个实例? (这是我目前的做法,详见下文)


更多详情:

那是我的 class(实际上是对它的极大简化):

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

而且,假设我有 3 个这样的实例 class。现在,如果我尝试将一个 属性 的值分配给另一个,该值将被简单地复制(正如预期的那样。我已经很清楚为什么会这样):

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.

我明白为什么会这样。但我想知道是否有一些 优雅 方法可以做到这一点:

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"

所以想法是分配一个字段作为对另一个对象的另一个字段的引用。我相信通过 属性 这是不可能的,因为它实际上是一种获取和设置私有字段的“方法”。

所以我这样做了,它有效,但它并不漂亮:

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"

寻求更优雅的方法,我什至尝试公开私有字段 _fullName(通过返回 ref 的方法),但我无法设置私有字段(也通过方法)将另一个对象作为对先前返回的引用对象的引用。它总是只是复制它的值。

我不熟悉 C# 10.0 的所有新功能,但您可以通过将名称本身视为一个对象并在每个 Person 实例中引用 Name 对象来实现所需的行为.即把它当作一个组合

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"

编辑:处理评论中解释的要求

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

    private readonly List<Person> _people = new List<Person>();

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

    public void Add(Person person)
    {
        _people.Add(person);
    }

    public void UpdateNames(Name name)
    {
        foreach (Person person in _people)
        {
            person.SetName(name);
        }
        _people.Clear();
    }
}

public class Person
{
    private Name _name;
    public Name Name
    {
        get => _name;
        set
        {
            _name.UpdateNames(value);
            _name = value;
        }
    }

    public string FullName => Name.FullName;

    public Person(Name name)
    {
        _name = name;
        _name.Add(this);
    }

    public void SetName(Name name)
    {
        _name = name;
        _name.Add(this);
    }
}

在我看来,实现您想要的最简单方法是使用 Func<string> 检索参考值:

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
}

或者这样写:

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
}