我正在使用一个按值在类之间传递对象的框架,我需要更新对其中一个对象的引用。我可以很好地更改原始对象的属性值,但似乎无法弄清楚如何更改对全新对象的引用。在后面的一个类中,我正在从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();
}
答案 0 :(得分:1)
您在内部局部函数中使用ref
关键字,但不在外部函数中使用。另外,如果实际上是要交换引用,则该方法不会照原样进行。
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;
}
}
}
SwapPersonFour
用对_person
的引用替换newPerson
字段。它实际上并没有交换任何内容,因为它在更新_person
时并未在更新newPerson
。完成后,它们都是对同一Person
的引用。 (您是要交换它们吗?可能是问题所在。)
对于它的价值,我将删除本地函数,因为它实际上不执行任何操作。该方法只需要做一件事,并将其嵌套在一个额外的函数中。您可以用它替换它并获得相同的结果-只是更容易阅读。 (实际上,多余的代码可能使您更容易错过没有被交换的内容。我不了解您,但是并不需要太多的困惑。)
public void SwapPersonFour(ref Person newPerson)
{
_person = newPerson;
}
如果您实际上想交换它们,则可以执行以下操作:
public void SwapPersonFour(ref Person newPerson)
{
var temp = _person;
_person = newPerson;
newPerson = temp;
}