レコードの種類を使用する

Tip

ソフトウェアの開発は初めてですか? 最初に、 作業の開始 に関するチュートリアルから始めます。 クラス、メソッド、ループに慣れることができます。

別の言語で経験がありますか? このチュートリアルでは、値の等価性、位置構文、 with 式など、毎日使用する C# レコード機能に焦点を当てます。

このチュートリアルでは、レコードとレコード構造体を使用して毎日の温度をモデル化するコンソール アプリを構築します。

このチュートリアルでは、以下の内容を学習します。

  • 位置指定レコードとレコード構造体を宣言します。
  • 小さなレコード階層を構築します。
  • コンパイラによって生成された等価性と書式設定を使用します。
  • 非破壊的変異には with 式を使用します。

前提条件

インストール手順

Windows では、この WinGet 構成ファイル を使用して、すべての前提条件をインストールします。 既に何かがインストールされている場合、WinGet はその手順をスキップします。

  1. ファイルをダウンロードし、ダブルクリックして実行します。
  2. 使用許諾契約書を読み、y と入力し、同意を求められたら Enter キーを選択します。
  3. タスク バーで点滅するユーザー アカウント制御 (UAC) プロンプトが表示された場合は、インストールを続行します。

他のプラットフォームでは、これらの各コンポーネントを個別にインストールする必要があります。

  1. 推奨されるインストーラーを .NET SDK ダウンロード ページからダウンロードし、ダブルクリックして実行します。 ダウンロード ページでプラットフォームが検出され、プラットフォームの最新のインストーラーが推奨されます。
  2. Visual Studio Codeホーム ページから最新のインストーラーをダウンロードし、ダブルクリックして実行します。 このページではプラットフォームも検出され、リンクはシステムに適している必要があります。
  3. C# DevKit 拡張機能ページの [インストール] ボタンをクリックします。 これで Visual Studio Code が開き、拡張機能をインストールするか有効にするかを確認するメッセージが表示されます。 [インストール] を選択します。

アプリと最初のレコードを作成する

アプリのフォルダーを作成し、 dotnet new console実行して、生成されたプロジェクトを開きます。

DailyTemperature.csという名前のファイルを追加し、温度値の位置指定readonly record structを追加します。

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

Program.csという名前のファイルを追加し、サンプル温度データを作成します。

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) 
];

この構文では、不変値セマンティクスを使用した簡潔なデータ モデリングが提供されます。

レコード構造体に動作を追加する

DailyTemperature.csでは、レコード構造体には既に計算された Mean プロパティがあります。

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

レコード構造体は、各値が小さく自己完結型であるため、ここでは適切に機能します。

度日計算向けレコード型を作成する

Note

加熱の日数冷却度日 は、1 日の平均温度が基準温度 (通常は 65°F/18°C) からどの程度逸脱しているかを測定します。 平均が基準を下回る寒い日には暖房度日が蓄積され、平均が基準を上回る暑い日には冷房度日が蓄積されます。 これらの計算は、暖房または冷却ビルのエネルギー消費量を見積もるのに役立ち、公益事業会社、ビル マネージャー、気候分析に役立ちます。

DegreeDays.csという名前のファイルを、暖房度日と冷却度日の計算のための階層で作成します。

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);
}

次に、MainProgram.csメソッドから合計を計算します。

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

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

生成された ToString 出力は、反復処理中の迅速な診断に役立ちます。

PrintMembersをオーバーライドして出力をカスタマイズする

既定の出力に含まれるノイズが多すぎる場合は、ベース レコードの PrintMembers をオーバーライドします。

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

オーバーライドにより、出力は必要な情報にフォーカスされます。

非破壊的な変異を伴う表現で使用する

withを使用して、元のレコードを変更せずに変更されたコピーを作成します。

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

そのアイデアを拡張して、入力データのスライスからローリング合計を計算します。

// 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);
}

この方法は、元の値を保持しながら変換が必要な場合に便利です。

次のステップ