|
|
Opublikowano 02.10.2023 09:25:51
|
|
|
|

Zaczynając od C# 9, możesz użyć modyfikatora rekordu, aby zdefiniować typ referencyjny, który zapewnia wbudowaną funkcjonalność do enkapsulacji danych. C# 10 pozwala na składnię klas rekordu jako synonim, aby wyjaśnić typy odniesień, a strukturze rekordu definiować typy wartości przy użyciu tej samej funkcjonalności.
Zastosowania zapisu w C#(Odpowiada ChatGPT):
Typ rekordu w C# to nowa funkcja wprowadzona w najnowszej wersji. Może być używany w wielu sytuacjach, w tym między innymi w następujących sytuacjach:
Niezmienny obiekt danych: Typ rekordu jest niezmienny, co oznacza, że po utworzeniu jego wartość właściwości nie może być zmieniona. Czyni je to idealnymi do reprezentowania niezmiennych struktur danych, takich jak obiekty transferowe (DTO) czy ustawienia konfiguracyjne. Obiekty wartości: Typ rekordu może być używany do reprezentowania obiektów wartości, których równość jest określana na podstawie wartości atrybutów, a nie równoważności referencyjnej. Dzięki temu są idealne do porównywania i przechowywania obiektów wartościowych, takich jak zakresy dat, punkty współrzędnych i inne. Dopasowanie wzorców: Typ rekordu może być używany razem z dopasowywaniem wzorców, co czyni go wygodniejszym przy pracy ze złożonymi strukturami danych. Możesz użyć wzorcowego dopasowania, aby sprawdzić i wyodrębnić wartości atrybutów obiektu rekordu, aby wykonać odpowiednią akcję. Kolekcje niezmienne: Typ rekordu może być używany z niezmiennymi typami kolekcji, takimi jak ImmutableList, ImmutableDictionary itp., do tworzenia obiektów kolekcji niezmiennych. Zapewnia to, że treść kolekcji nie jest modyfikowana, co poprawia niezawodność i bezpieczeństwo kodu. To tylko kilka przypadków użycia tego typu rekordu, a Ty możesz zdecydować, czy go użyć, w zależności od swoich potrzeb i struktury kodu. Różnica między zapisem a klasą oraz strukturą
Składnia używana przy deklarowaniu i instancjonowaniu klasy lub struktury jest taka sama jak przy zapisywaniu operacji. Po prostu zamień słowo kluczowe class na record lub użyj record struct zamiast struct. Podobnie, klasa rekordu obsługuje tę samą składnię dla relacji dziedziczenia. Różnica między rekordem a klasą wygląda następująco:
- Możesz użyć parametrów pozycyjnych w głównym konstruktorze do tworzenia i instancji typów o niezmiennych właściwościach.
- Metody i operatory wskazujące równość odniesienia lub nierówność w klasach (np. Object.Equals(Object) oraz ==) wskazują równość wartości lub brak równości w rekordzie.
- Możesz użyć wyrażenia with do stworzenia kopii niezmiennego obiektu z nową wartością w wybranym atrybucie.
- Metoda ToString w rekordzie tworzy ciąg formatu, który wyświetla nazwę typu obiektu oraz nazwy i wartości wszystkich jego wspólnych właściwości.
- Rekord może być odziedziczony z innego rekordu. Jednak zapisy nie mogą być dziedziczone z klas, ani klasy nie mogą być dziedziczone z rejestrów.
- Różnica między strukturą rekordu a strukturą polega na tym, że kompilator syntetyzuje metody do określania równości i ToString. Kompilator syntetyzuje metodę Deconstruct dla struktury rekordu pozycji.
Kompilator syntetyzuje wspólną właściwość inicjalizacji dla każdego głównego parametru konstruktora w klasie rekordu. W strukturze rekordu kompilator syntetyzuje publiczne właściwości odczytu/zapisu. Kompilator nie tworzy właściwości dla głównych argumentów konstruktora w typach klas i struktur, które nie zawierają modyfikatora rekordu.
rekord
Typ odniesienia do klasy rekordu (domyślnie: klasa może zostać pomijana) Typ wartości struktury zapisu
Gramatyka Cukier
Rekord jest w rzeczywistości taki, żeSyntax sugar, a końcowy efekt to kod klasowy lub strukturalny。 Weźmy następujący kod jako przykład:
Na koniec kompiluje się do następującego kodu:
z wykorzystaniem System; używając System.Collections.Generic; za pomocą System.Diagnostics; używając System.Reflection; używając System.Runtime.CompilerServices; używając System.Security; używając System.Security.Permissions; używając System.Text; używając Microsoft.CodeAnalysis;
[assembly: CompilationRelaxations(8)] [assembly: Runtime Compatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue | DebuggableAttribute.DebuggingModes.DisableOptimizations)] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [moduł: UnverifiableCode] [moduł: System.Runtime.CompilerServices.RefSafetyRules(11)]
[System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] Osoba w klasie publicznej: IEw.<PersonInfo>
{ [KompilatorGenerowany] [DebuggerBrowsable(DebuggerBrowsableState.Never)] prywatny ciąg tekstu tylko do odczytu <FirstName>k__BackingField;
[KompilatorGenerowany] [DebuggerBrowsable(DebuggerBrowsableState.Never)] prywatny k__BackingField tekstu tylko do odczytu<LastName>;
[KompilatorGenerowany] chroniony wirtualny Typ EqualityContract { [KompilatorGenerowany] Pobierz { return typeof(PersonInfo); } }
publiczny string FirstName { [KompilatorGenerowany] Pobierz { powrót <FirstName>k__BackingField; } [KompilatorGenerowany] Init { <FirstName>k__BackingField = wartość; } }
publiczny string Nazwisko { [KompilatorGenerowany] Pobierz { powrót <LastName>k__BackingField; } [KompilatorGenerowany] Init { <LastName>k__BackingField = wartość; } }
public PersonInfo(ciąg Imię, ciąg Nazwisko) { <FirstName>k__BackingField = Imię; <LastName>k__BackingField = Nazwisko; baza.. ctor(); }
[KompilatorGenerowany] public override string ToString() { StringBuilder stringBuilder = nowy StringBuilder(); stringBuilder.Append("PersonInfo"); stringBuilder.Append(" { "); if (PrintMembers(stringBuilder)) { stringBuilder.Append(' '); } stringBuilder.Append('}'); return stringBuilder.ToString(); }
[KompilatorGenerowany] chroniony wirtualny bool PrintMembers (StringBuilder builder) { RuntimeHelpers.EnsureSufficientExecutionStack(); budowniczy. Dodaj("FirstName = "); budowniczy. Dodaj((object)FirstName); budowniczy. Dołączymy(", NazwiskoNazwiska = "); budowniczy. Dodaj (obiekt)Nazwisko); return true; }
[System.Runtime.CompilerServices.NullableContext(2)] [KompilatorGenerowany] publiczny statyczny operator boolu !=(PersonInfo po lewej, PersonInfo po prawej) { wrócić! (lewa == prawa); }
[System.Runtime.CompilerServices.NullableContext(2)] [KompilatorGenerowany] publiczny statyczny bool operator ==(PersonInfo po lewej, PersonInfo po prawej) { return (object)left == right || ((obiekt)left != null & left. Równy (po prawej); }
[KompilatorGenerowany] public overpass int GetHashCode() { return (EqualityComparer<Type>. Default.GetHashCode(EqualityContract) * -1521134295 + EqualityComparer<string>. Default.GetHashCode(<FirstName>k__BackingField)) * -1521134295 + EqualityComparer<string>. Default.GetHashCode(<LastName>k__BackingField); }
[System.Runtime.CompilerServices.NullableContext(2)] [KompilatorGenerowany] public override bool Equals (object obj) { return Equals(obj jako PersonInfo); }
[System.Runtime.CompilerServices.NullableContext(2)] [KompilatorGenerowany] publiczny wirtualny bool Equals (PersonInfo inne) { return (obiekt)to == inne || ((obiekt)inne != null && EqualityContract == inne. EqualityContract & EqualityComparer<string>. Default.Equals(<FirstName>k__BackingField, inne.<FirstName>k__BackingField) & EqualityComparer<string>. Default.Equal(<LastName>k__BackingField, inne.<LastName>k__BackingField)); }
[KompilatorGenerowany] publicznie wirtualne PersonInfo <Clone>$() { zwróć nową PersonInfo(to); }
[KompilatorGenerowany] chroniona PersonInfo (oryginalna PersonInfo) { <FirstName>k__BackingField = oryginalny. <FirstName>k__BackingField; <LastName>k__BackingField = oryginalny. <LastName>k__BackingField; }
[KompilatorGenerowany] public void Deconstruct(out string FirstName, out string LastName) { ImięImię = to. Imię; Nazwisko = to. Nazwisko; }
}
przestrzeń nazw Microsoft.CodeAnalysis
{ [KompilatorGenerowany] [Wbudowane] wewnętrzna zamknięta klasa EmbeddedAttribute : Attribute { }
}
przestrzeń nazw System.Runtime.CompilerServices
{ [KompilatorGenerowany] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] wewnętrzna zamknięta klasa NullableAttribute : Attribute { public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0) { bajt[] array = nowy bajt[1]; array[0] = P_0; NullableFlags = tablica; }
public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } }
[KompilatorGenerowany] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] wewnętrzna zamknięta klasa NullableContextAttribute : Attribute { publiczny bajt tylko do odczytu Flag;
public NullableContextAttribute(byte P_0) { Flaga = P_0; } }
[KompilatorGenerowany] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] wewnętrzna zamknięta klasa RefSafetyRulesAttribute : Attribute { publiczna wersja tylko do odczytu int;
publiczna RefSafetyRulesAttribute(int P_0) { Wersja = P_0; } }
} Automatycznie generuje konstruktory, przepisuje metody ToString, GetHashCode, Equals oraz automatycznie generuje niektóre metody.
p1 i p2 to w rzeczywistości dwa różne obiekty, ale ponieważ kompilator automatycznie generował komparator (IEquatable) i przepisywał metody Equals oraz GetHashCode, wynik był prawdziwy. Wywołanie metody ToString jest również bardzo intuicyjne do wygenerowania zapisanej wartości. Jak pokazano poniżej:
rekord
Wymagane:wymagany modyfikator oznacza, że pole lub atrybut, który stosuje, musi zostać zainicjalizowany przez wszystkich konstruktorów lub za pomocą inicjalizatora obiektu. Każde wyrażenie użyte do inicjalizacji nowej instancji tego typu musi inicjalizować wszystkie wymagane członki. Odniesienie:Logowanie do linku jest widoczne.
Init: W C# 9 i późniejszych wyrazy kluczowe init definiują metodę accessora w właściwości lub indeksatorze. Biblioteka tylko init przypisuje wartości atrybutom lub elementom indeksującym tylko podczas budowy obiektów. To wymusza niezmienność, więc po inicjalizacji obiektu nie można go już zmieniać. Odniesienie:Logowanie do linku jest widoczne.
z: Jeśli musisz replikować instancję z pewnymi modyfikacjami, możesz użyć wyrażenia with do implementacji niedestrukcyjnych zmian. z wyrażeniem do utworzenia nowej instancji rekordu, będącej kopią istniejącej instancji rekordu, modyfikując określone właściwości i pola. Odniesienie:Logowanie do linku jest widoczne.
Zatem rekord można zdefiniować następująco:
wymagany, init, nie wspominając o tym, że faktycznie jest to syntaktyczny cukier, to będzieWołaj <Clone>automatycznie generowaną metodę $a następnie modyfikować wartość atrybutu. Następujący sposób:
Kod:
Atrybut rekordu
Czasami musimy dodać do atrybutów pewne funkcje, takie jak funkcje serializacji JSON, informacje opisowe itp.
Zasoby:
Logowanie do linku jest widoczne.
Logowanie do linku jest widoczne.
|
Poprzedni:ASP.NET Core (24) opiera się na komunikacji wysokiej wydajności Refit, MemoryPackNastępny:GitHub korzysta z API REST do przeglądania rozmiarów repozytoriów
|