« Record » : différence entre les versions
Aucun résumé des modifications |
|||
(17 versions intermédiaires par le même utilisateur non affichées) | |||
Ligne 4 : | Ligne 4 : | ||
= Definition = | = Definition = | ||
Built-in functionality for encapsulating immutable data.<br> | |||
C# 10 allows the {{boxx|record class}} syntax as a synonym to clarify a reference type, and {{boxx|record struct}} to define a value type. | |||
= Primary constructor = | = Primary constructor = | ||
Ligne 17 : | Ligne 18 : | ||
public required string LastName { 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; } | |||
} | |||
</kode> | |||
== Default parameter == | |||
Default value parameters must be compile time consistant.<br> | |||
For none compile time consistant value, you have to set it with the property. | |||
<kode lang='cs'> | |||
public record MyRecord(string Name) | |||
{ | |||
// 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> | |||
= [https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/record#immutability Immutability] = | |||
Immutability means the data of the record don't change after its creation.<br> | |||
It is useful when you need thread-safe data-centric types or expect hash codes remaining the sames.<br> | |||
However, the data that a reference-type property refers to can be changed: | |||
<kode lang='cs'> | |||
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"; | |||
</kode> | |||
= [https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/record#value-equality Value equality] = | |||
Two record objects are equal if they are of the same type and store the same values. | |||
<kode lang='cs'> | |||
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); | |||
</kode> | |||
= [https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/record#nondestructive-mutation Nondestructive mutation] = | |||
Allow to copy and modify the copy only.<br> | |||
It calls the clone method and then sets the properties that are specified in the {{boxx|with}} expression. | |||
{{warn | It is equivalent to a Shallow Copy: the value of value type field is copied, the reference of refence type field is copied.<br> | |||
To make it work, have value type fields only or record fields or [https://learn.microsoft.com/en-us/archive/msdn-magazine/2017/march/net-framework-immutable-collections immutable collections]}} | |||
<kode lang='cs'> | |||
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 | |||
</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.
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.
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
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:
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.
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 |
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 |