Zrozumienie właściwości w C#
C# 11, wprowadzony wraz z .NET 7, przyniósł ekscytujący dodatek do własności: słowo kluczowe required. W tym artykułe zbadamy właściwości C# z przykładami z zwięzłego samouczka wideo Tima Coreya pt. ".NET 7 Update: Required Properties in 10 Minutes or Less". Rozłożymy wszystko od podstaw właściwości po nowe słowo kluczowe required i sposób, w jaki pomaga ono wymusić zasady inicjalizacji.
Właściwości C
W C# właściwości pozwalają kapsułkować pola i zarządzać dostępem do członków danych klasy obiektu. Są powszechnie używane do zapewniania integralności danych przy jednoczesnym umożliwieniu dostępu zewnętrznego. Prywatne pole można kapsułkować za pomocą właściwości, oferując kontrolę nad sposobem dostępu do danych lub ich modyfikacji. Publiczne właściwości typu string często korzystają ze specjalnych metod zwanych akcesorami (get i set) do efektywnego manipulowania członkami klasy. Statyczna właściwość w C# może być dostępna bez tworzenia instancji klasy, oferując unikalny sposób zarządzania wartościami właściwości.
Oto jak Tim ustawia prosty przykład właściwości do demonstracji.
Tworzenie aplikacji konsolowej
Najpierw Tim zaczyna od podstawowej aplikacji konsolowej .NET 7 przy użyciu C# 11. Ta wersja wprowadza słowo kluczowe required, które nie jest dostępne w poprzednich wersjach .NET.
Definiowanie prostego modelu
Tim tworzy klasę PersonModel z właściwościami dla FirstName i LastName:
public class PersonModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class PersonModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
Te właściwości pozwalają PersonModel przechowywać imię i nazwisko. Jednak bez dodatkowej konfiguracji FirstName i LastName mogą potencjalnie pozostać niezainicjalizowane, co prowadzi do wartości null.
Używanie konstruktorów do zapewnienia inicjalizacji
Powszechnym sposobem zapewnienia, że właściwości są zawsze inicjowane, jest użycie konstruktora. W przykładzie Tima, dodaje on konstruktor do bazowej klasy PersonModel, który wymaga zarówno FirstName, jak i LastName:
public PersonModel(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
public PersonModel(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
To podejście wymusza, że za każdym razem, gdy tworzony jest obiekt PersonModel, zarówno FirstName, jak i LastName muszą być dostarczone. Jeśli chcielibyśmy utworzyć PersonModel bez określenia tych wartości, kompilator zgłosiłby to jako błąd.
Kontekst dla nullables
Począwszy od .NET 6 i C# 10, C# wprowadził odwołania mogące być nullem. To oznacza, że właściwości muszą być albo inicjowane, albo wyraźnie oznaczone jako mogące być nullem za pomocą ?. Na przykład, jeśli FirstName i LastName mogą być nullem, zdefiniujemy je w następujący sposób:
public string? FirstName { get; set; }
public string? LastName { get; set; }
public string? FirstName { get; set; }
public string? LastName { get; set; }
W przykładzie Tima zakładamy jednak, że FirstName i LastName powinny zawsze mieć nienullowe wartości. Początkowo, obsługę nullów zapewniała ostrożna inicjalizacja lub adnotacje nullables, ale wraz z C# 11, mamy bardziej solidne opcje.
Wprowadzenie słowa kluczowego required
Chociaż konstruktory mogą wymuszać inicjalizację, C# 11 wprowadza słowo kluczowe required, co ułatwia zapewnienie ustawienia konkretnych właściwości. Za pomocą required można oznaczać pojedyncze właściwości jako wymagańe, co oznacza, że muszą mieć przypisaną wartość podczas inicjalizacji obiektu.
Konfiguracja właściwości required
Aby FirstName i LastName stały się właściwościami wymagańymi, Tim w 4:15 modyfikuje klasę PersonModel w następujący sposób:
public class PersonModel
{
public required string FirstName { get; set; }
public required string LastName { get; set; }
}
public class PersonModel
{
public required string FirstName { get; set; }
public required string LastName { get; set; }
}
Oznaczając te właściwości za pomocą required, kompilator teraz wymusi, by zostały ustawione za pomocą inicjalizatora obiektu lub konstruktora. Jest to przydatne, ponieważ pozwala na wymaganie określonych właściwości bez konieczności tworzenia konstruktora.
Przykładowe zastosowanie z wymagańymi właściwościami
Teraz możemy utworzyć i zainicjować PersonModel w następujący sposób:
PersonModel person = new() { FirstName = "Tim", LastName = "Corey" };
PersonModel person = new() { FirstName = "Tim", LastName = "Corey" };
Jeśli pominiemy FirstName lub LastName, kompilator zgłosi błąd, nakłaniając nas do zainicjalizowania tych wymagańych właściwości.
Użycie required z konstruktorami
Tim demonstruje przypadek, w którym zarówno required właściwości, jak i konstruktory są używane. W sytuacjach, gdy mamy do czynienia z konstruktorem, który ustawia wymagańe właściwości, język C# musi zapewnić, że właściwości te są nadal inicjowane w momencie wywołania konstruktora.
W takich przypadkach można użyć atrybutu SetsRequiredMembers, aby zasygnalizować, że konstruktor spełnia wymagańe warunki. Oto, jak Tim to stosuje:
[SetsRequiredMembers]
public PersonModel()
{
FirstName = "Test";
LastName = "Test";
}
[SetsRequiredMembers]
public PersonModel(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
[SetsRequiredMembers]
public PersonModel()
{
FirstName = "Test";
LastName = "Test";
}
[SetsRequiredMembers]
public PersonModel(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
Dodanie SetsRequiredMembers informuje kompilator, że te właściwości zostaną ustawione w obrębie konstruktora, unikając błędów inicjalizacji. Ta funkcja pomaga zapobiegać przypadkowym pominięciom, zapewniając jednocześnie elastyczność w inicjalizacji właściwości.
Dłączego wymagańe właściwości są przydatne
Tim wyjaśnia, że nowe słowo kluczowe required usprawnia proces zapewniania, że właściwości zawsze są ustawione. Zamiast potrzebować konstruktorów dla metody set w każdym przypadku lub ryzykować niezdefiniowane właściwości, mamy teraz prosty sposób na wymaganie konkretnych wartości bezpośrednio w deklaracji właściwości.
Ta funkcja sprawdza się w modelach danych, w których niektóre pola są obowiązkowe, i może pomóc w wykryciu problemów na wczesnym etapie procesu programowania poprzez zapobieganie błędom null w czasie wykonywania.
Przykład dodatkowych właściwości
Tim dodał następnie opcjonalną właściwość, Email, która może być nullem:
public string? Email { get; set; }
public string? Email { get; set; }
Ponieważ nie jest oznaczona za pomocą required, właściwość Email może pozostać nieustawiona bez powodowania błędu kompilacji. Na tym przykładzie Tim zademonstrował elastyczność, jaką zapewnia klasa z wyraźnym rozróżnieniem między polami danych niezbędnymi a opcjonalnymi.
Wnioski
Dodanie wymagańych właściwości w C# 11 jest cenną funkcją dla programistów, zapewniającą, że niezbędne właściwości są zawsze inicjowane. Film Tima Coreya stanowi doskonałe wprowadzenie do tej funkcji i pokazuje, jak działa ona w aplikacji konsolowej. Łącząc required ze wstępnymi inicjalizacjami obiektów i konstruktorami, możemy tworzyć bardziej solidne i bezpieczne modele danych w C#. Aby uzyskać więcej przydatnych samouczków, odwiedź kanał Tima na YouTube.
