{"componentChunkName":"component---src-templates-blog-post-js","path":"/blog/csharp-historia-9-0","result":{"data":{"markdownRemark":{"html":"<p>Prześledźmy, jakie nowinki były wprowadzane w kolejnych wersjach C# (wybór) - w odwrotnie chronologicznej kolejności, najpierw wersja 9.0.</p>\n<h2>Rekordy</h2>\n<p>Skrótowa składnia dla klas, które jedynie przechowują dane. Innymi słowy - zamiast rozwlekłego:</p>\n<div class=\"gatsby-highlight\" data-language=\"csharp\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-csharp line-numbers\"><code class=\"language-csharp\"><span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">Student</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">public</span> <span class=\"token return-type class-name\"><span class=\"token keyword\">string</span></span> FirstName <span class=\"token punctuation\">{</span><span class=\"token keyword\">get</span><span class=\"token punctuation\">;</span> <span class=\"token keyword\">private</span> <span class=\"token keyword\">set</span><span class=\"token punctuation\">;</span><span class=\"token punctuation\">}</span>\n    <span class=\"token keyword\">public</span> <span class=\"token return-type class-name\"><span class=\"token keyword\">string</span></span> LastName <span class=\"token punctuation\">{</span><span class=\"token keyword\">get</span><span class=\"token punctuation\">;</span> <span class=\"token keyword\">private</span> <span class=\"token keyword\">set</span><span class=\"token punctuation\">;</span><span class=\"token punctuation\">}</span>\n\n    <span class=\"token keyword\">public</span> <span class=\"token function\">Student</span><span class=\"token punctuation\">(</span><span class=\"token class-name\"><span class=\"token keyword\">string</span></span> firstName<span class=\"token punctuation\">,</span> <span class=\"token class-name\"><span class=\"token keyword\">string</span></span> lastName<span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span>\n        FirstName <span class=\"token operator\">=</span> firstName<span class=\"token punctuation\">;</span>\n        LastName <span class=\"token operator\">=</span> lastName<span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>Możemy to zapisać tak:</p>\n<div class=\"gatsby-highlight\" data-language=\"csharp\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-csharp line-numbers\"><code class=\"language-csharp\"><span class=\"token keyword\">public</span> <span class=\"token return-type class-name\">record</span> <span class=\"token function\">Student</span><span class=\"token punctuation\">(</span><span class=\"token class-name\"><span class=\"token keyword\">string</span></span> FirstName<span class=\"token punctuation\">,</span> <span class=\"token class-name\"><span class=\"token keyword\">string</span></span> LastName<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span></span></pre></div>\n<p>P.S. Zwróć uwagę na to, że zmienne w rekordzie są PascalCase - w ten sposób uzyskamy właściwości o \"klasycznym\" case'ingu.\nP.P.S. Rekordy mogą dziedziczyć tylko po rekordach - i na odwrót (tylko przez rekordy mogą być dziedziczone).</p>\n<h2>Init-only setters</h2>\n<p>W powyższym, pierwotnym, przykładzie ze studentem cały \"myk\" polegał na tym, żeby uniemożliwić modyfikację właściwości, tj. żeby nadać wartość tylko raz, podczas inicjalizacji obiektu. W tej chwili możemy jednak napisać w klasie <code class=\"language-text\">Student</code> metodę, która, już po zainicjalizowaniu obiektu, będzie modyfikować wartość którejś z właściwości. Oczywiście, można temu zapobiec - po prostu mieć pole oznaczone jako <code class=\"language-text\">readonly</code>, a właściwość tylko jako getter odczytujący z tegoż pola. To by było jednak już zupełnie rozwlekłe. Stąd w C# 9.0 wprowadzono nowe słowo kluczowe: <code class=\"language-text\">init</code>. Zobaczmy je w akcji:</p>\n<div class=\"gatsby-highlight\" data-language=\"csharp\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-csharp line-numbers\"><code class=\"language-csharp\"><span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">Student</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">public</span> <span class=\"token return-type class-name\"><span class=\"token keyword\">string</span></span> FirstName <span class=\"token punctuation\">{</span><span class=\"token keyword\">get</span><span class=\"token punctuation\">;</span> init<span class=\"token punctuation\">;</span><span class=\"token punctuation\">}</span>\n    <span class=\"token keyword\">public</span> <span class=\"token return-type class-name\"><span class=\"token keyword\">string</span></span> LastName <span class=\"token punctuation\">{</span><span class=\"token keyword\">get</span><span class=\"token punctuation\">;</span> init<span class=\"token punctuation\">;</span><span class=\"token punctuation\">}</span>\n\n    <span class=\"token keyword\">public</span> <span class=\"token return-type class-name\"><span class=\"token keyword\">void</span></span> <span class=\"token function\">ChangeFirstName</span><span class=\"token punctuation\">(</span><span class=\"token class-name\"><span class=\"token keyword\">string</span></span> firstName<span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span>\n        FirstName <span class=\"token operator\">=</span> firstName<span class=\"token punctuation\">;</span> <span class=\"token comment\">// &lt;-- TO SIĘ NIE SKOMPILUJE!!!</span>\n    <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>W ten sposób otrzymujemy klasę, która też jest podobna do rekordu - ale inicjalizujemy ją inaczej:</p>\n<div class=\"gatsby-highlight\" data-language=\"csharp\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-csharp line-numbers\"><code class=\"language-csharp\"><span class=\"token class-name\"><span class=\"token keyword\">var</span></span> student <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token constructor-invocation class-name\">Student</span> <span class=\"token punctuation\">{</span>\n    FirstName <span class=\"token operator\">=</span> <span class=\"token string\">\"John\"</span><span class=\"token punctuation\">,</span>\n    LastName <span class=\"token operator\">=</span> <span class=\"token string\">\"Smith\"</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\nstudent<span class=\"token punctuation\">.</span>FirstName <span class=\"token operator\">=</span> <span class=\"token string\">\"Johnny\"</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// &lt;-- TO SIĘ NIE SKOMPILUJE!!!</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>Po zainicjalizowaniu obiektu nie ma opcji, żeby zmienić wartość właściwości: czy to z zewnątrz, czy z wewnątrz klasy.</p>\n<p>P.S. Oczywiście przykład z blokowaniem zmiany personaliów studenta może być mylący. W normalnym życiu przecież możliwa jest taka zmiana: od zwykłej omyłki na zmianie stanu cywilnego studenta kończąc. :)</p>\n<h2>Pomijanie typu przy słowie kluczowym <code class=\"language-text\">new</code></h2>\n<p>W sytuacji, gdy kompilator potrafi domyślić się typu, wystarczy, że zawołamy samo <code class=\"language-text\">new()</code>, bez podawania typu, np. przy deklaracji pola:</p>\n<div class=\"gatsby-highlight\" data-language=\"csharp\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-csharp line-numbers\"><code class=\"language-csharp\"><span class=\"token keyword\">private</span> <span class=\"token class-name\">List<span class=\"token punctuation\">&lt;</span><span class=\"token keyword\">string</span><span class=\"token punctuation\">></span></span> list <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span></span></pre></div>\n<p>Albo gdy przekazujemy parametr do metody:</p>\n<div class=\"gatsby-highlight\" data-language=\"csharp\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-csharp line-numbers\"><code class=\"language-csharp\"><span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">Car</span><span class=\"token punctuation\">{</span>\n<span class=\"token keyword\">public</span> <span class=\"token function\">Car</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Engine</span> engine<span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">Engine</span><span class=\"token punctuation\">{</span>\n<span class=\"token keyword\">public</span> <span class=\"token return-type class-name\"><span class=\"token keyword\">bool</span></span> IsDiesel <span class=\"token punctuation\">{</span><span class=\"token keyword\">get</span><span class=\"token punctuation\">;</span> init<span class=\"token punctuation\">;</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token class-name\"><span class=\"token keyword\">var</span></span> dieselCar <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token constructor-invocation class-name\">Car</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">new</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span>IsDiesel<span class=\"token operator\">=</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>To może ułatwić życie przy późniejszych refaktoryzacjach - zwłaszcza wtedy, gdy dokonujemy nie zmiany nazwy klasy (to nam załatwią narzędzia dziś dostępne), ale gdy np. rozbijamy jakąś klasę na dwie: nie musimy ręcznie poprawiać wszystkich wywołań konstruktorów (o ile oczywiście nie zmienią się parametry...).</p>","excerpt":"Prześledźmy, jakie nowinki były wprowadzane w kolejnych wersjach C# (wybór) - w odwrotnie chronologicznej kolejności, najpierw wersja 9.0. Rekordy Skrótowa…","frontmatter":{"date":"10 July, 2021","path":"/blog/csharp-historia-9-0","title":"C# - historia (C# 9.0)"},"fields":{"readingTime":{"text":"3 min read"}}}},"pageContext":{}},"staticQueryHashes":["3649515864","63159454"]}