« Record » : différence entre les versions

De Banane Atomic
Aller à la navigationAller à la recherche
 
(Une version intermédiaire par le même utilisateur non affichée)
Ligne 44 : Ligne 44 :
public record MyRecord(string Name)
public record MyRecord(string Name)
{
{
     public required IReadOnlyCollection<string> Tags { get; init; } = [];
    // no need to have the required keyword, because there is a default value
     public IReadOnlyCollection<string> Tags { get; init; } = [];
}
}
</kode>
== [https://www.claudiobernasconi.ch/2023/03/08/the-required-keyword-and-record-types-in-csharp-11/ Use both the constructor and the object initializer] ==
<kode lang='cs'>
public record MyRecord
{
    public MyRecord()
    { }
    [SetsRequiredMembers]
    public MyRecord(int id, string name)
    {
        Id = id;
        Name = name;
    }
    public required int Id { get; init; }
    public required string Name { get; init; }
}
var r1 = new MyRecord(1, "One");
var r2 = new MyRecord
{
    Id = 2,
    Name = "Two"
};
</kode>
</kode>



Dernière version du 17 septembre 2024 à 12:37

Links

Definition

Built-in functionality for encapsulating immutable data.
C# 10 allows the record class syntax as a synonym to clarify a reference type, and record struct to define a value type.

Primary constructor

When you declare a primary constructor on a record, the compiler generates public properties for the primary constructor parameters.

Cs.svg
public record Person(string FirstName, string LastName);

// with the generated properties it is equivalent to
public record Person
{
    public required string FirstName { get; init; }
    public required string LastName { get; init; }
};

// record struct value type with immutable properties
public readonly record struct Point(double X, double Y);
// equivalent to
public record struct Point
{
    public double X { get; init; }
    public double Y { get; init; }
}

// record struct value type with mutable properties
public record struct Point(double X, double Y);
// equivalent to
public record struct Point
{
    public double X { get; set; }
    public double Y { get; set; }
}

Default parameter

Default value parameters must be compile time consistant.
For none compile time consistant value, you have to set it with the property.

Cs.svg
public record MyRecord(string Name)
{
    // no need to have the required keyword, because there is a default value
    public IReadOnlyCollection<string> Tags { get; init; } = [];
}

Use both the constructor and the object initializer

Cs.svg
public record MyRecord
{
    public MyRecord()
    { }

    [SetsRequiredMembers]
    public MyRecord(int id, string name)
    {
        Id = id;
        Name = name;
    }

    public required int Id { get; init; }
    public required string Name { get; init; }
}

var r1 = new MyRecord(1, "One");
var r2 = new MyRecord
{
    Id = 2,
    Name = "Two"
};

Immutability

Immutability means the data of the record don't change after its creation.
It is useful when you need thread-safe data-centric types or expect hash codes remaining the sames.
However, the data that a reference-type property refers to can be changed:

Cs.svg
public record Person(string Name, string[] PhoneNumbers);

Person person = new("Nicolas", new string[1] { "06-10-20-30-40" });
// the PhoneNumbers array is immutable, but the string in the array are mutable
person.PhoneNumbers[0] = "06-11-22-33-44";

Value equality

Two record objects are equal if they are of the same type and store the same values.

Cs.svg
string[] phoneNumbers = [ "06-10-20-30-40" ];
Person person1 = new("Nicolas", phoneNumbers);
Person person2 = new("Nicolas", phoneNumbers);
Console.WriteLine(person1 == person2); // true

Person person1 = new("Nicolas", [ "06-10-20-30-40" ]);
Person person2 = new("Nicolas", [ "06-10-20-30-40" ]);
Console.WriteLine(person1 == person2); // false because array are compared by reference not by value

public record Person(string Name, string[] PhoneNumbers);

Nondestructive mutation

Allow to copy and modify the copy only.
It calls the clone method and then sets the properties that are specified in the with expression.

It is equivalent to a Shallow Copy: the value of value type field is copied, the reference of refence type field is copied.
To make it work, have value type fields only or record fields or immutable collections
Cs.svg
Person person1 = new("Nicolas", [ "06-10-20-30-40" ]);
Person person2 = person1 with { Name = "Audrey" };

var person3 = person1 with { };  // copy without modification
Console.WriteLine(person1 == person3); // true