Używanie typów rekordów

Wskazówka

Dopiero zaczynasz programować oprogramowanie? Najpierw zacznij od samouczków Wprowadzenie . Oswajasz się z klasami, metodami i pętlami.

Czy masz doświadczenie w pracy w innym języku? Ten samouczek koncentruje się na funkcjach rekordów języka C# używanych codziennie: równości wartości, składni pozycyjnej i with wyrażeń.

W tym samouczku utworzysz aplikację konsolową, która modeluje dzienne temperatury przy użyciu rekordów i struktur rekordów.

W tym poradniku nauczysz się, jak:

  • Deklarowanie rekordów pozycyjnych i struktur rekordów.
  • Utwórz małą hierarchię rekordów.
  • Używaj operatorów równości i formatowania generowanych przez kompilator.
  • Użyj with wyrażeń dla mutacji niestrukcyjnej.

Prerequisites

Instrukcje instalacji

W systemie Windows ten plik konfiguracyjny WinGet służy do instalacji wszystkich wymagań wstępnych. Jeśli masz już coś zainstalowanego, usługa WinGet pominie ten krok.

  1. Pobierz plik i kliknij dwukrotnie, aby go uruchomić.
  2. Przeczytaj umowę licencyjną, wpisz yi wybierz pozycję Wprowadź po wyświetleniu monitu o zaakceptowanie.
  3. Jeśli na pasku zadań zostanie wyświetlony monit kontroli konta użytkownika (UAC), zezwól na kontynuowanie instalacji.

Na innych platformach należy zainstalować każdy z tych składników oddzielnie.

  1. Pobierz zalecany instalator ze strony pobierania zestawu SDK .NET i kliknij dwukrotnie, aby go uruchomić. Strona pobierania wykrywa platformę i zaleca najnowszy instalator twojej platformy.
  2. Pobierz najnowszy instalator z strony głównej programu Visual Studio Code i kliknij dwukrotnie, aby go uruchomić. Ta strona wykrywa również platformę, a link powinien być poprawny dla twojego systemu.
  3. Kliknij przycisk "Zainstaluj" na stronie rozszerzenia C# DevKit. Spowoduje to otwarcie Visual Studio kodu i pytanie, czy chcesz zainstalować lub włączyć rozszerzenie. Wybierz pozycję "Zainstaluj".

Tworzenie aplikacji i pierwszego rekordu

Utwórz folder dla aplikacji, uruchom dotnet new console, i otwórz wygenerowany projekt.

Dodaj plik o nazwie DailyTemperature.cs, a następnie dodaj parametr pozycyjny readonly record struct dla wartości temperatury:

public readonly record struct DailyTemperature(double HighTemp, double LowTemp)
{
    public double Mean => (HighTemp + LowTemp) / 2.0;
}

Dodaj plik o nazwie Program.csi utwórz przykładowe dane temperatury:

private static DailyTemperature[] data = [
    new DailyTemperature(HighTemp: 57, LowTemp: 30), 
    new DailyTemperature(60, 35),
    new DailyTemperature(63, 33),
    new DailyTemperature(68, 29),
    new DailyTemperature(72, 47),
    new DailyTemperature(75, 55),
    new DailyTemperature(77, 55),
    new DailyTemperature(72, 58),
    new DailyTemperature(70, 47),
    new DailyTemperature(77, 59),
    new DailyTemperature(85, 65),
    new DailyTemperature(87, 65),
    new DailyTemperature(85, 72),
    new DailyTemperature(83, 68),
    new DailyTemperature(77, 65),
    new DailyTemperature(72, 58),
    new DailyTemperature(77, 55),
    new DailyTemperature(76, 53),
    new DailyTemperature(80, 60),
    new DailyTemperature(85, 66) 
];

Ta składnia zapewnia zwięzłe modelowanie danych z niezmiennymi semantykami wartości.

Dodawanie zachowania do struktury rekordów

W DailyTemperature.cs, struktura rekordu ma już obliczoną właściwość Mean.

public double Mean => (HighTemp + LowTemp) / 2.0;

Struktura rekordów działa dobrze, ponieważ każda wartość jest mała i samodzielna.

Tworzenie typów rekordów na potrzeby obliczeń stopniodniowych

Note

Dzienni stopnie ogrzewania i dzienni stopnie chłodzenia mierzą, o ile średnia temperatura dzienna odbiega od temperatury bazowej (zazwyczaj 65°F/18°C). Stopnie-dni ogrzewania gromadzą się podczas zimnych dni, jeśli średnia jest poniżej bazowej, podczas gdy stopnie-dni chłodzenia gromadzą się podczas ciepłych dni, jeśli średnia przekracza bazę. Te obliczenia pomagają oszacować zużycie energii do ogrzewania lub chłodzenia budynków, co czyni je przydatnymi dla firm użyteczności publicznej, menedżerów budynków i analizy klimatu.

Utwórz plik o nazwie DegreeDays.cs z hierarchią na potrzeby obliczeń stopni ogrzewania i chłodzenia:

public abstract record DegreeDays(double BaseTemperature, IEnumerable<DailyTemperature> TempRecords);

public sealed record HeatingDegreeDays(double BaseTemperature, IEnumerable<DailyTemperature> TempRecords)
    : DegreeDays(BaseTemperature, TempRecords)
{
    public double DegreeDays => TempRecords.Where(s => s.Mean < BaseTemperature).Sum(s => BaseTemperature - s.Mean);
}

public sealed record CoolingDegreeDays(double BaseTemperature, IEnumerable<DailyTemperature> TempRecords)
    : DegreeDays(BaseTemperature, TempRecords)
{
    public double DegreeDays => TempRecords.Where(s => s.Mean > BaseTemperature).Sum(s => s.Mean - BaseTemperature);
}

Teraz oblicz sumy przy użyciu metody Main w Program.cs.

var heatingDegreeDays = new HeatingDegreeDays(65, data);
Console.WriteLine(heatingDegreeDays);

var coolingDegreeDays = new CoolingDegreeDays(65, data);
Console.WriteLine(coolingDegreeDays);

Wygenerowane ToString dane wyjściowe są przydatne w przypadku szybkiej diagnostyki podczas iteracji.

Nadpisz PrintMembers w celu dostosowania wyniku

Gdy domyślne dane wyjściowe zawierają zbyt dużo szumu, przesłoń PrintMembers w rekordzie podstawowym:

protected virtual bool PrintMembers(StringBuilder stringBuilder)
{
    stringBuilder.Append($"BaseTemperature = {BaseTemperature}");
    return true;
}

Przesłonięcie pozwala skoncentrować się na informacjach, które są potrzebne.

Używanie z wyrażeniami dla mutacji niestrukcyjnej

Użyj with polecenia, aby utworzyć zmodyfikowane kopie bez modyfikowania oryginalnego rekordu.

// Growing degree days measure warming to determine plant growing rates
var growingDegreeDays = coolingDegreeDays with { BaseTemperature = 41 };
Console.WriteLine(growingDegreeDays);

Rozszerz ten pomysł, aby obliczyć sumy stopniowe z wycinków danych wejściowych:

// showing moving accumulation of 5 days using range syntax
List<CoolingDegreeDays> movingAccumulation = new();
int rangeSize = (data.Length > 5) ? 5 : data.Length;
for (int start = 0; start < data.Length - rangeSize; start++)
{
    var fiveDayTotal = growingDegreeDays with { TempRecords = data[start..(start + rangeSize)] };
    movingAccumulation.Add(fiveDayTotal);
}
Console.WriteLine();
Console.WriteLine("Total degree days in the last five days");
foreach(var item in movingAccumulation)
{
    Console.WriteLine(item);
}

Takie podejście jest przydatne, gdy potrzebne są przekształcenia podczas zachowywania oryginalnych wartości.

Następne kroki