C# - historia (C# 9.0)

2021-07-10

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 składnia dla klas, które jedynie przechowują dane. Innymi słowy - zamiast rozwlekłego:

public class Student {
    public string FirstName {get; private set;}
    public string LastName {get; private set;}

    public Student(string firstName, string lastName){
        FirstName = firstName;
        LastName = lastName;
    }
}

Możemy to zapisać tak:

public record Student(string FirstName, string LastName);

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. P.P.S. Rekordy mogą dziedziczyć tylko po rekordach - i na odwrót (tylko przez rekordy mogą być dziedziczone).

Init-only setters

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 Student 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 readonly, 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: init. Zobaczmy je w akcji:

public class Student {
    public string FirstName {get; init;}
    public string LastName {get; init;}

    public void ChangeFirstName(string firstName){
        FirstName = firstName; // <-- TO SIĘ NIE SKOMPILUJE!!!
    }
}

W ten sposób otrzymujemy klasę, która też jest podobna do rekordu - ale inicjalizujemy ją inaczej:

var student = new Student {
    FirstName = "John",
    LastName = "Smith"
};

student.FirstName = "Johnny"; // <-- TO SIĘ NIE SKOMPILUJE!!!

Po zainicjalizowaniu obiektu nie ma opcji, żeby zmienić wartość właściwości: czy to z zewnątrz, czy z wewnątrz klasy.

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. :)

Pomijanie typu przy słowie kluczowym new

W sytuacji, gdy kompilator potrafi domyślić się typu, wystarczy, że zawołamy samo new(), bez podawania typu, np. przy deklaracji pola:

private List<string> list = new();

Albo gdy przekazujemy parametr do metody:

public class Car{
public Car(Engine engine){}
}

public class Engine{
public bool IsDiesel {get; init;}
}

var dieselCar = new Car(new(){IsDiesel=true});

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…).


Robert Skarżycki - zdjęcie profilowe

Pisanina, której autorem jest Robert Skarżycki - programista .NET, mąż szczęśliwej żony, rodzic
moje bio
mój Twitter
mój LinkedIn
moje szkolenia i warsztaty

© 2022, Built with Gatsby & passion