如何更新按值传递的参考类型的参考



我正在使用一个框架,该框架通过值在类之间传递对象,我需要更新对其中一个对象的引用。我可以可以更改原始对象的属性值,但是我似乎无法弄清楚如何更改对一个全新对象的引用。在后者的一个类中,我是从API中检索一个相当复杂的对象,因此我渴望更新参考而不是尝试深层副本。

我尝试在我的代码样本中调用SwapPerson{One,Two,Three,Four},但没有成功的迹象。输出始终是:

Main.person: Groucho Marx is 128 years old!
Main.person: Groucho Marx is 129 years old!
Main.person: Groucho Marx is 129 years old!

我希望有一个简单的解决方案,因为深夜,我要忽略了一个简单的解决方案,因此任何输入都非常感谢。

    public class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int Age { get; set; }
        public override string ToString()
        {
            return $"{FirstName} {LastName} is {Age} years old!";
        }
    }
    public class Foo
    {
        private Person person;
        public Foo(Person person)
        {
            this.person = person;
        }
        public void SetAge(int age)
        {
            person.Age = age;
        }
        public void SwapPersonOne(Person newPerson)
        {
            person = newPerson;
        }
        public void SwapPersonTwo(ref Person newPerson)
        {
            person = newPerson;
        }
        public void SwapPersonThree(Person newPerson)
        {
            LocalSwap(ref person);
            void LocalSwap(ref Person oldPerson)
            {
                oldPerson = newPerson;
            }
        }
        public void SwapPersonFour(Person newPerson)
        {
            LocalSwap(ref person, ref newPerson);
            void LocalSwap(ref Person oldPerson, ref Person _newPerson)
            {
                oldPerson = _newPerson;
            }
        }
    }
    static void Main(string[] args)
    {
        Person person = new Person { FirstName = "Groucho", LastName = "Marx", Age = 128 };
        Console.WriteLine($"{nameof(Main)}.{nameof(person)}: {person}");
        var foo = new Foo(person);
        foo.SetAge(129);
        Console.WriteLine($"{nameof(Main)}.{nameof(person)}: {person}");
        var charlie = new Person { FirstName = "Charlie", LastName = "Chaplin", Age = 130 };
        //foo.SwapPersonOne(charlie);
        //foo.SwapPersonTwo(ref charlie);
        //foo.SwapPersonThree(charlie);
        foo.SwapPersonFour(charlie);
        Console.WriteLine($"{nameof(Main)}.{nameof(person)}: {person}");
        Console.ReadLine();
    }

您正在使用内部本地函数中的ref关键字,但在外部函数中不使用。另外,如果意图实际上是 swap 参考文献,则该方法不这样做。

    public void SwapPersonFour(Person newPerson)
    {
        LocalSwap(ref person, ref newPerson);
        void LocalSwap(ref Person oldPerson, ref Person _newPerson)
        {
            oldPerson = _newPerson;
        }
    }

oldPerson_newPerson通过参考传递给本地函数,但 newPerson按值传递给 SwapPersonFour

另外,仅更新oldPerson,因此现在oldPerson_newPerson都请参考同一Person

如果要更新传递给SwapPersonFour的引用,则还必须使用ref关键字来传递该参数。

public void SwapPersonFour(ref Person newPerson)

评论提到它不起作用,所以我整理了一个仓促的单位测试,看看我是否缺少某些东西。(我一直都想念东西,这就是我编写单元测试的原因。(

[TestClass]
public class UnitTest1
{
    private Person _person;
    [TestMethod]
    public void TestSwappingPerson()
    {
        _person = new Person { FirstName = "Scott" };
        var newPerson = new Person() { FirstName = "Bob" };
        SwapPersonFour(ref newPerson);
        Assert.AreEqual("Bob", _person.FirstName);
    }
    public void SwapPersonFour(ref Person newPerson)
    {
        LocalSwap(ref _person, ref newPerson);
        void LocalSwap(ref Person oldPerson, ref Person localNewPerson)
        {
            oldPerson = localNewPerson;
        }
    }
}

SwapPersonFournewPerson的引用替换_person字段。它实际上并没有交换任何内容,因为当它更新_person时,它没有更新newPerson。完成后,它们都是同一Person的引用。(您是要交换它们吗?这可能是问题。(

对于它的价值,我会删除本地功能,因为它实际上没有做任何事情。它只需要该方法做的一件事,然后将其嵌套在额外的功能中。您可以用它替换它并获得相同的结果 - 它更容易阅读。(实际上,额外的代码可能会让您更容易错过任何东西。

public void SwapPersonFour(ref Person newPerson)
{
    _person = newPerson;
}

如果您实际上想交换它们,则可以这样做:

public void SwapPersonFour(ref Person newPerson)
{
    var temp = _person;
    _person = newPerson;
    newPerson = temp;
}

最新更新