.net DeepCloner实际上没有复制属性?

2cmtqfgy  于 2023-01-22  发布在  .NET
关注(0)|答案(1)|浏览(187)

所以我一直在尝试使用一个叫做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”?

piah890a

piah890a1#

在当前编写的代码中,您正在为destination参数分配一个全新的对象。但这并不会更改您传递给该参数的对象。要克服此问题,有几种可能性(按我个人偏好的顺序)
1.您可以只定义PerformDeepCloning来返回Person

public static Person PerformDeepCloning(Person source)
 {
   //call a method from the package
   Person destination = source.DeepClone();
   //this works fine
   Console.WriteLine("DEEP CLONED NAME = " + destination.Name);
   return Person
 }

这样称呼它

Person otherPersion = PerformDeepCloning(person);

对我来说,这似乎是最自然的方法,与其填充返回void的方法的outref参数,为什么不直接通过return关键字返回结果呢?
1.使用out keyword,它是专门为这种情况设计的(即在被调用的方法中创建一个新对象,如果return由于任何原因而不可行,则将其传递给调用者)

public static void PerformDeepCloning(Person source, out Person destination)
 {
   //call a method from the package
   destination = source.DeepClone();
   //this works fine
   Console.WriteLine("DEEP CLONED NAME = " + destination.Name);
 }

然后这样称呼它

//you must not assign a value here, when using the out keyword        
 Person otherPerson;
 PerformDeepCloning(person, out otherPerson);

或者从C#7开始,您还可以使用内联声明

//no need to delare Person otherPerson; prior to the call
 PerformDeepCloning(person, out Person otherPerson);

1.使用能够更新传入的引用的ref keyword

public static void PerformDeepCloning(Person source, ref Person destination)
 {
   //call a method from the package
   destination = source.DeepClone();
   //this works fine
   Console.WriteLine("DEEP CLONED NAME = " + destination.Name);
 }

然后这样称呼它

Person otherPerson = new Person(); 
 PerformDeepCloning(person, ref otherPerson);

但是当你创建一个Person的新示例时,你不需要在调用之前创建一个新对象(因为这个对象会被立即丢弃),而是用null初始化otherPerson,但是你当然要确保,在你创建一个示例之前,你不需要访问otherPerson的属性。

Person otherPerson = null; 
 PerformDeepCloning(person, ref otherPerson);

相关问题