所以我一直在尝试使用一个叫做DeepCloner的NuGet软件包。
我有一个名为 IdInfo 的简单类,它有一个属性和构造函数
public class IdInfo
{
public int IdNumber;
public IdInfo(int idNumber)
{
IdNumber = idNumber;
}
}
然后,我有一个名为 Person 的类,它包含几个属性和构造函数
public class Person
{
public int Age;
public DateTime BirthDate;
public string Name;
public IdInfo IdInfo;
public Person(int age, DateTime birthDate, string name, IdInfo idInfo)
{
Age = age;
BirthDate = birthDate;
Name = name;
IdInfo = idInfo;
}
public Person()
{ }
}
在我的主课程中,我想通过上面提到的DeepCloner来实现深度克隆,这是我尝试过的
internal class Program
{
static void Main(string[] args)
{
//create a dummy Person to get cloned
Person p1 = new Person();
p1.Age = 42;
p1.BirthDate = Convert.ToDateTime("1977-01-05");
p1.Name = "Aleksandar Petrovic";
p1.IdInfo = new IdInfo(123);
//create a dummy Person to append those values to
Person clonedPerson = new Person();
//call a method for DeepCloning (down in the code)
PerformDeepCloning(p1, clonedPerson);
//after finishing with the method, "clonedPerson" value stay null, why?
Console.WriteLine("Displaying values of both persons (1. p1, 2. Cloned person)\n");
DisplayValues(p1);
//System.NullReferenceException: 'Object reference not set to an instance of an object.'
DisplayValues(clonedPerson);
}
public static void DisplayValues(Person p)
{
Console.WriteLine(" Name: {0:s}, Age: {1:d}, BirthDate: {2:MM/dd/yy}", p.Name, p.Age, p.BirthDate);
Console.WriteLine(" ID#: {0:d}\n", p.IdInfo.IdNumber);
}
//method gets 2 elements, first has values that should be copied to the second
public static void PerformDeepCloning(Person source, Person destination)
{
//call a method from the package
destination = source.DeepClone();
//this works fine
Console.WriteLine("DEEP CLONED NAME = " + destination.Name);
}
}
我理解为什么这些值显示在下面的SC中
但是为什么这些值之后没有应用于变量“clonedPerson”?
1条答案
按热度按时间piah890a1#
在当前编写的代码中,您正在为
destination
参数分配一个全新的对象。但这并不会更改您传递给该参数的对象。要克服此问题,有几种可能性(按我个人偏好的顺序)1.您可以只定义
PerformDeepCloning
来返回Person
这样称呼它
对我来说,这似乎是最自然的方法,与其填充返回
void
的方法的out
或ref
参数,为什么不直接通过return
关键字返回结果呢?1.使用
out
keyword,它是专门为这种情况设计的(即在被调用的方法中创建一个新对象,如果return
由于任何原因而不可行,则将其传递给调用者)然后这样称呼它
或者从C#7开始,您还可以使用内联声明
1.使用能够更新传入的引用的
ref
keyword。然后这样称呼它
但是当你创建一个
Person
的新示例时,你不需要在调用之前创建一个新对象(因为这个对象会被立即丢弃),而是用null
初始化otherPerson
,但是你当然要确保,在你创建一个示例之前,你不需要访问otherPerson
的属性。