-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrecords.dib
175 lines (128 loc) · 4.58 KB
/
records.dib
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#!meta
{"kernelInfo":{"defaultKernelName":null,"items":[{"name":"csharp","languageName":"C#","aliases":["c#","cs"]},{"name":"fsharp","languageName":"F#","aliases":["f#","fs"]},{"name":"pwsh","languageName":"PowerShell","aliases":["powershell"]},{"name":"javascript","languageName":"JavaScript","aliases":["js"]},{"name":"html","languageName":"HTML"},{"name":"sql","languageName":"SQL"},{"name":"kql","languageName":"KQL"},{"name":"mermaid","languageName":"Mermaid"},{"name":"httpRequest","languageName":"http"},{"name":"value"}]}}
#!markdown
Records in C#
#!csharp
public class Course
{
public string Name {get; set;}
public string Author {get; set;}
}
var course = new Course();
course.Name = "Duck Hunting";
course.Author = "John Doe";
Console.WriteLine($"Course 1:\n{course.Name}\n{course.Author}");
#!csharp
var course2 = course;
course2.Name = "Cat Hunting";
Console.WriteLine($"Course 1:\n{course.Name}\n{course.Author}");
Console.WriteLine($"\nCourse 2:\n{course2.Name}\n{course2.Author}");
// Both entries have changed, because when initializing second course with first one, we have used the REFERENCE.
#!csharp
static void PrintCourse(Course course)
{
Console.WriteLine(course.Name);
}
PrintCourse(course);
#!csharp
// Record type with two string properties - Name and Author
public record CourseRecord(string Name, string Author);
// POSITIONAL RECORD
// can't create instance without providing declared properties
var course3 = new CourseRecord("Witch Hunting", "John Doe");
// A RECORD INSTANCE IS IMMUTABLE
// ITS VALUES CANNOT CHANGE ONCE THE OBJECT WAS CONSTRUCTED
// course3.Name = "Another Title";
#!markdown
Record is an immutable reference type
Objects that shouldn't change shouldn't be changeable
Do the properties of a DTO need to change in web application?
No, because it would no longer represent the data that was sent.
#!csharp
public object ConvertToObject(Course course)
{
// Positional records cannot use paranthesis object creation, because there is no parameterless constructor
// return CourseRecord()
// {
// Name = "John"
// }
// we need to use constructor with parameters
return new CourseRecord(course.Name, course.Author);
}
#!csharp
// Record descructuring
// order of deconstruction is as it was declard in record
var (name, author) = course3;
Console.WriteLine($"{name}, {author}");
#!csharp
// Deconstructing class object
// this will not work
// var (name, author) = Course;
public class CourseWithDeconstruct : Course
{
// here's how we can make it work
public void Deconstruct(out string name, out string author)
{
name = Name;
author = Author;
}
}
var course4 = new CourseWithDeconstruct()
{
Name = "Dog Hunting",
Author = "John Doe"
};
// now it works B)
var (name, author) = course4;
#!csharp
// Record cloning
var clone = course3 with { Author = "John Boe" };
// won't work on regular class
// var clonedClass = course4 with { Name = "John Boe" };
#!csharp
// Custom Record Types
// record body can contain anything class body can
// constructor and deconstructor is only generated for positional properties
public record AdvancedRecord(string Name)
{
// overriding default constructor
// public AdvancedRecord(string Name, string Author) : this() {}
public AdvancedRecord(string name, string author) : this(name) {}
// alternative of using property as class arguments
// we use init as setter!
// public string Name { get; init; }
// Init keyword can be used in classes as well
public string Author { get; init; }
// custom property
// lets use take control of getter and setter
public String Title
{
get
{
return $"{Name} - {Author}";
}
}
}
var course1 = new AdvancedRecord("Book X")
{
Author = "John Doe"
};
var course2 = new AdvancedRecord("Book X", "John Doe");
#!csharp
// Inheritance and polymorphism
// we can derive from record but we need to redeclare all the props and then pass them to class that we are deriving too
// we cannot derive from sealed record
public record UltraAdvancedRecord(string Name, int Duration) : AdvancedRecord(Name);
// when cloning object of derived class we will get object of base class
// behind the scene though it is still of derived class type
#!csharp
// Synthetized methods
public record SynthetizerRecord(string Name, string Author)
{
// can override only two methods
}
public record SynthetizerRecordExtended(string Name, string Author, int Age) : SynthetizerRecord(Name, Author)
{
// can override 4 methods and one prop
}
// in IL a record is basically a class :)