Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to copy/clone records in C# 9?

The C# 9 records feature specification includes the following:

A record type contains two copying members:

A constructor taking a single argument of the record type. It is referred to as a "copy constructor". A synthesized public parameterless instance "clone" method with a compiler-reserved name

But I cannot seem to call either of these two copying members:

public record R(int A);
// ...
var r2 = new R(r); // ERROR: inaccessible due to protection level
var r3 = r.Clone(); // ERROR: R does not contain a definition for Clone

From this, I understand that the constructor is protected and thus can't be accessed outside the record's inheritance hierarchy. And so we're left with code like this:

var r4 = r with { };

But what about cloning? The clone method is public according to the specification above. But what is its name? Or is it an effectively random string so that it should not be called outside the record's inheritance hierarchy? If so, what is the correct way to deep copy records? It seems from the specification that one is able to create one's own clone method. Is this so, and what would be an example of how it should work?

like image 425
mbabramo Avatar asked Sep 21 '20 14:09

mbabramo


People also ask

What is deep or shallow copy concept in C #?

This is called “Shallow Copy”. To get the same behavior for a Reference Type as well as a Value Type we use the Clone() method that belongs to the System. ICloneable interface. This is called a “Deep Copy”. We will see both behaviors in depth one by one.


Video Answer


2 Answers

But what about cloning?

var r4 = r with { };

performs a shallow clone on r.

The clone method is public according to the specification above. But what is its name?

The C# compiler has a fairly common trick where it gives generated members names which are illegal in C#, but legal in IL, so that they can't be called except from the compiler, even if they're public. In this case the name of the Clone method is <Clone>$.

If so, what is the correct way to deep copy records?

Deep copying you're out of luck. However since records should ideally be immutable, there should be no difference in practice between a shallow copy, a deep copy, and the original instance.

It seems from the specification that one is able to create one's own clone method. Is this so, and what would be an example of how it should work?

Unfortunately this didn't make the cut for C# 9, but there's a strong chance it'll be in C# 10.

like image 193
Yair Halberstadt Avatar answered Oct 16 '22 10:10

Yair Halberstadt


To perform deep clone, you add your own copy constructor to a record:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public record EmployeeRecord(int UniqueId, Person Employee)
{

    // Custom copy constructor (Should be protected or private)
    protected EmployeeRecord(EmployeeRecord other)
    {
        UniqueId = other.UniqueId;

        // Do deep copy stuff
        Employee = new Person 
        { 
            FirstName = Employee.FirstName, 
            LastName = Employee.LastName 
        };
    }
}

The compiler will not generate its own in this case. Then you use the "with" keyword:

var emp1 = new EmployeeRecord(100, 
    new Person { FirstName = "John", LastName = "Doe" });

var emp2 = emp1 with { };
like image 2
Mike Russo Avatar answered Oct 16 '22 11:10

Mike Russo