C# | 2週間で身につくアプリを作りながら学ぶC#の基本 - 14日目

C# C#
スポンサーリンク

14日目のゴールとテーマ

14日目のテーマは「2週間で作ってきたものを“振り返りながら仕上げる”」です。
今日は新しい文法をどんどん増やす日ではなく、

今ある診断アプリを「自分の手で少し改造してみる」
2週間で学んだ C# の基本を、頭の中でつなぎ直す
「次に何を学ぶか」を自分で選べる状態になる

ここをゴールにします。

なので今日は、

今のアプリに小さな機能を1つ足す
コード全体を“言葉で説明できる”ようにする
この2週間で身についたことを整理する

という流れでいきます。


いまのアプリの“全体像”を言葉で説明してみる

アプリの構造を上から眺める

ここまでで作ってきた診断アプリは、ざっくり言うとこういう構造でした。

Program
アプリの入口。メニューを出し、ユーザーの選択に応じて処理を振り分ける。

Result
1 回分の診断結果を表すクラス。
日時・はいの数・質問数・タイプコードを持ち、
ログとの変換やラベル表示のロジックも持っている。

ResultRepository
ログファイル(log.txt)から Result を読み込んだり、
新しい Result を追記したりするクラス。

ResultService
複数の Result をまとめて扱い、
「最近5件を表示」「タイプ別件数を表示」などの集計・表示を担当するクラス。

これを自分の言葉で説明できるようになると、
「コードをただ書いた」から「構造を理解している」に一段上がります。


小さな機能追加で“自分のアプリ”にする

今日は「日付で絞り込んで表示する」機能を足してみる

新しい文法を増やすより、
今あるものに小さな機能を足す方が、理解が深まります。

例として、こんな機能を足してみましょう。

「指定した日付以降の履歴だけを表示する」

イメージとしては、

メニューに「4: 日付で絞り込んで履歴を見る」を追加
ユーザーに「2026-03-01」のような日付を入力してもらう
その日付以降の Result だけを LINQ で抽出して表示

という流れです。


日付を文字列から DateTime に変換する

安全にパースするための DateTime.TryParse

ユーザーに日付を入力してもらうとき、
いきなり DateTime.Parse を使うと、
形式が違ったときに例外で落ちてしまいます。

そこで、数値のときと同じように TryParse を使います。

static DateTime ReadDate()
{
    while (true)
    {
        Console.Write("日付を yyyy-MM-dd 形式で入力してください(例: 2026-03-02): ");
        string input = Console.ReadLine();

        if (DateTime.TryParse(input, out DateTime date))
        {
            return date.Date;
        }
        else
        {
            Console.WriteLine("日付の形式が正しくありません。もう一度入力してください。");
        }
    }
}
C#

ここでの重要ポイントはこうです。

DateTime.TryParse は、成功したら true、失敗したら false
例外を投げないので、入力ミスに優しく対応できる
date.Date としているのは「時刻部分を切り捨てて日付だけにする」ため

これで、「正しい形式の入力が来るまで聞き続ける」ことができます。


ResultService に「日付で絞り込んで表示する」メソッドを追加する

LINQ で「指定日付以降」を抽出する

ResultService に、次のようなメソッドを追加します。

public void ShowFromDate(DateTime fromDate)
{
    var filtered = _results
        .Where(r => r.Timestamp.Date >= fromDate.Date)
        .OrderBy(r => r.Timestamp);

    Console.WriteLine("=== " + fromDate.ToString("yyyy-MM-dd") + " 以降の履歴 ===");

    bool hasAny = false;

    foreach (var r in filtered)
    {
        hasAny = true;

        Console.WriteLine(
            r.Timestamp.ToString("yyyy-MM-dd HH:mm")
            + "  "
            + r.YesCount + "/" + r.Total
            + "  "
            + r.GetTypeLabel()
        );
    }

    if (!hasAny)
    {
        Console.WriteLine("該当する履歴はありません。");
    }

    Console.WriteLine();
}
C#

ここで深掘りしたいポイントは次です。

Where で「条件に合うものだけ」を抽出している
r.Timestamp.Date >= fromDate.Date で「その日以降」を判定
OrderBy で古い順に並べている(最近順にしたければ OrderByDescending)
1 件もなかった場合に備えて、hasAny フラグでチェックしている

LINQ の Where は、「フィルタする」という意味で非常に重要です。
ここまで来ると、LINQ が「データに対する日本語のような命令」に見えてくるはずです。


メニューに新しい項目を追加する

Program.Main に 4 番の選択肢を足す

メニュー部分を少しだけ改造します。

Console.WriteLine("=== メニュー ===");
Console.WriteLine("0: 終了");
Console.WriteLine("1: 最近の履歴を見る");
Console.WriteLine("2: タイプ別件数を見る");
Console.WriteLine("3: 新しい診断を行う");
Console.WriteLine("4: 日付を指定して履歴を見る");
Console.WriteLine();
C#

選択処理も 4 を追加します。

if (choice == 0)
{
    Console.WriteLine("終了します。");
    break;
}

if (choice == 1)
{
    HandleShowRecent(repo);
}
else if (choice == 2)
{
    HandleShowSummary(repo);
}
else if (choice == 3)
{
    HandleNewDiagnosis(repo);
}
else if (choice == 4)
{
    HandleShowFromDate(repo);
}
C#

日付指定の処理をハンドラとして分ける

static void HandleShowFromDate(ResultRepository repo)
{
    DateTime fromDate = ReadDate();

    var results = repo.LoadAll();
    var service = new ResultService(results);

    service.ShowFromDate(fromDate);
}
C#

ここでも「役割分担」が生きています。

日付の入力 → Program 側(ReadDate)
データの読み込み → ResultRepository
絞り込みと表示 → ResultService

この分担が自然にできているなら、
オブジェクト指向の感覚はかなりいい線まで来ています。


2週間で学んだ C# の“核”を整理する

文法レベルで身についたこと

コンソール入出力
Console.WriteLineConsole.ReadLine で、画面とのやりとりができる。

条件分岐
if / else / else if で、条件によって処理を変えられる。

繰り返し
forwhile で、同じ処理を何度も実行できる。

配列と List
string[]List<Result> で、複数のデータをまとめて扱える。

メソッド
引数と戻り値を持つ「処理の部品」を作り、
Main から呼び出してコードを整理できる。

例外処理
try / catchTryParse で、エラーに強いコードを書ける。

C# らしい“構造”として身についたこと

クラス
Result のように、自分で「意味のある型」を定義できる。

オブジェクト
new Result() のように、クラスから実体を作って扱える。

責任の分割
Result(データ)、ResultRepository(保存)、ResultService(集計)、Program(司令塔)
というように、役割ごとにクラスを分けられる。

LINQ
Where / OrderBy / Take / GroupBy / Average などで、
データ処理を短く、意図が伝わる形で書ける。

ファイル入出力
File.ReadAllLines / File.AppendAllText / File.Exists で、
アプリに「記憶」を持たせられる。

ここまでを 2 週間で触れているので、
「C# の入門を終えた」というより、
「C# で小さな実用アプリを組み立てられる入り口に立った」状態です。


これから先に進むための道しるべ

この診断アプリをどう発展させてもいい

例えば、こんな方向に伸ばせます。

診断の種類を増やす
インドア度だけでなく、「仕事スタイル診断」「学習タイプ診断」などを追加し、
メニューから診断の種類を選べるようにする。

保存形式を変える
今はカンマ区切りのテキストですが、
JSON 形式にしてみると、Web や他の言語との連携に近づきます。

UI を変える
コンソールではなく、
WPF や WinForms、あるいは Web(ASP.NET)で画面を作ってみる。

どの方向に進んでも、
この 2 週間で作った「小さな診断アプリの骨格」はそのまま土台になります。

最後に、あなたにやってほしいこと

今日の締めとして、こんなことをやってみてほしいです。

この 2 週間で書いた(あるいは読んだ)コードの中から、
「これは自分で説明できる」と思う部分を 1 つ選ぶ。

そして、それを 日本語で説明してみてください。

「このクラスは何をしているのか」
「このメソッドは何を入力にして、何を返しているのか」
「この LINQ の 1 行は、データに対して何をしているのか」

コードを“読む力”と“説明する力”がつくと、
次に学ぶことの吸収スピードが一気に上がります。

タイトルとURLをコピーしました