第6章:Controller入門①:入力を受けて“指示する”係🎮➡️🧠
この章は 「MVCがちゃんと回り始める最初の山」 だよ〜!⛰️✨ Model(データ)と View(表示)を作ったら、次はそれらをつなぐ Controller(交通整理) の出番🚦💨
6章のゴール🎯✨
この章が終わったら、こうなってるのが理想👇
- Controllerが 「入力を受ける」→「どの処理を呼ぶか決める」→「表示をお願いする」 係だと説明できる🗣️✨
listコマンドで Todo 一覧が出せる✅- Viewにロジックを混ぜない、Controllerを太らせない感覚がうっすら掴める🌱
Controllerってなに?一言でいうと…🚦✨

Controllerは 「ユーザー操作の受付係」 だよ🙋♀️ ユーザーが何か入力したら、それを受け取って…
- 「何したいの?」を読み取って🔎
- 「じゃあこの処理ね!」ってModel側に指示して📦
- 「表示お願い!」ってViewに頼む🎨
…っていう 交通整理 をする係🚥✨
まず“やること / やらないこと”をハッキリしよう✂️✅
Controllerがやること🙆♀️
- 入力を受け取る(コマンド文字列など)⌨️
- 入力の“形”チェック(空、数値じゃない…みたいな)🔎
- どの処理を呼ぶか振り分ける(今回のメイン!)📮
- 画面に何を出すかを決めてViewにお願いする👀
Controllerがやらないこと🙅♀️
- データのルールを持つ(それはModelの仕事)📦🛡️ 例:「タイトル空欄NG」とか
- 表示の装飾にこだわる(それはViewの仕事)🎨 例:「枠線どうする?」とか
今回作るもの(ミニ完成形)🧁✨
通し課題 CampusTodo で、まずは list コマンドだけ動かすよ✅
list→ Todo一覧を表示📋✨help→ 使い方を表示🆘exit→ 終了👋
ちなみに最新のC#は C# 14 で、.NET 10 上でサポートされてるよ〜。(Microsoft Learn) Visual Studio 2026 には .NET 10 SDK が入ってる、って明記されてるよ。(Microsoft Learn)
フォルダ構成(この章でのおすすめ)📁✨
Consoleアプリでも「役割の部屋」を分けると一気にMVCっぽくなるよ〜🏠✨
-
Models/TodoItem.csTodoStore.cs(メモリに保持するだけの簡易ストア)
-
Views/TodoView.cs
-
Controllers/TodoController.cs
-
Program.cs
実装ステップ①:Model(最低限)📦✨
TodoItem.cs
namespace CampusTodo.Models;
public class TodoItem
{
public int Id { get; }
public string Title { get; }
public bool IsDone { get; private set; }
public TodoItem(int id, string title)
{
if (string.IsNullOrWhiteSpace(title))
throw new ArgumentException("タイトルが空だよ🥺", nameof(title));
Id = id;
Title = title.Trim();
IsDone = false;
}
public void MarkDone() => IsDone = true;
}
TodoStore.cs(今回は“仮データ置き場”)
using CampusTodo.Models;
namespace CampusTodo.Models;
public class TodoStore
{
private readonly List<TodoItem> _items = new();
public TodoStore()
{
// 仮データ(第4章で作った想定でもOK!)
_items.Add(new TodoItem(1, "レポート下書き"));
_items.Add(new TodoItem(2, "ゼミの資料作り"));
_items.Add(new TodoItem(3, "洗濯する"));
}
public IReadOnlyList<TodoItem> GetAll() => _items;
}
実装ステップ②:View(表示だけ!)🎨✨
TodoView.cs
using CampusTodo.Models;
namespace CampusTodo.Views;
public class TodoView
{
public void ShowWelcome()
{
Console.WriteLine("CampusTodoへようこそ〜!🎓✨");
Console.WriteLine("help と打つと使い方が出るよ🆘");
Console.WriteLine();
}
public void ShowHelp()
{
Console.WriteLine("使い方📘✨");
Console.WriteLine(" list : 一覧を見る📋");
Console.WriteLine(" help : 使い方🆘");
Console.WriteLine(" exit : 終了👋");
Console.WriteLine();
}
public void ShowList(IReadOnlyList<TodoItem> items)
{
Console.WriteLine("Todo一覧📋✨");
if (items.Count == 0)
{
Console.WriteLine(" まだ何もないよ〜🌱");
Console.WriteLine();
return;
}
foreach (var item in items)
{
var mark = item.IsDone ? "✅" : "⬜";
Console.WriteLine($" {mark} {item.Id}. {item.Title}");
}
Console.WriteLine();
}
public void ShowError(string message)
{
Console.WriteLine($"エラーだよ〜🥺:{message}");
Console.WriteLine();
}
public void ShowUnknownCommand(string? cmd)
{
Console.WriteLine($"「{cmd}」は知らないコマンドかも…🤔");
Console.WriteLine("help を見てね🆘");
Console.WriteLine();
}
}
実装ステップ③:Controller(この章の主役!)🎮🚦✨
ポイントはこれ👇 Controllerは 「入力を読む」→「振り分ける」→「Model/Viewを呼ぶ」 だけ!
TodoController.cs
using CampusTodo.Models;
using CampusTodo.Views;
namespace CampusTodo.Controllers;
public class TodoController
{
private readonly TodoStore _store;
private readonly TodoView _view;
public TodoController(TodoStore store, TodoView view)
{
_store = store;
_view = view;
}
public void Run()
{
_view.ShowWelcome();
while (true)
{
Console.Write("> ");
var line = Console.ReadLine();
if (line is null)
return; // 入力ストリームが閉じた
var cmd = line.Trim();
if (cmd.Length == 0)
continue;
// 今回は “超シンプル” に:最初の単語だけで判定
var first = cmd.Split(' ', StringSplitOptions.RemoveEmptyEntries)[0]
.ToLowerInvariant();
switch (first)
{
case "list":
HandleList();
break;
case "help":
_view.ShowHelp();
break;
case "exit":
case "quit":
Console.WriteLine("またね〜👋✨");
return;
default:
_view.ShowUnknownCommand(first);
break;
}
}
}
private void HandleList()
{
// Controllerは「取ってきて表示して〜」って段取りするだけ
var items = _store.GetAll();
_view.ShowList(items);
}
}
実装ステップ④:Program.cs(全部つなぐ🔌✨)
using CampusTodo.Controllers;
using CampusTodo.Models;
using CampusTodo.Views;
var store = new TodoStore();
var view = new TodoView();
var controller = new TodoController(store, view);
controller.Run();
動作確認(イメージ)👀✨
CampusTodoへようこそ〜!🎓✨
help と打つと使い方が出るよ🆘
> list
Todo一覧📋✨
⬜ 1. レポート下書き
⬜ 2. ゼミの資料作り
⬜ 3. 洗濯する
> help
使い方📘✨
list : 一覧を見る📋
help : 使い方🆘
exit : 終了👋
> exit
またね〜👋✨
つまずきポイントあるある集🥺🧯
- Viewに処理を書いちゃう
例:
ShowList()の中でstore.GetAll()し始める → 責務混ざる😵💫 - Controllerが全部やり始める(Fat Controllerの芽🌱) 今回はOKだけど、増えてきたら第12章のService層で分けるよ🍔➡️🥗
- 入力パースが雑で落ちる まずは「help出す」「エラーでも落ちない」が正義😌✨
AI活用コーナー🤖💡(この章で効くやつ)
1) コマンド設計案を出してもらう🧾✨
- 「CampusTodoのコマンド案を、初心者が覚えやすい形で5個。短い理由つきで」
2) Controllerが責務を守れてるかレビューしてもらう🧐
- 「このControllerのコード見て、Controllerがやりすぎてる所があれば指摘して。理由もお願い」
3) switch地獄になりそうな予兆チェック⚠️
- 「コマンドが増えたときにswitchが読みにくくなる兆候と、今できる小さな対策を3つ教えて」
ミニ演習(この章の宿題)📚✅✨
演習A:list をちょい進化させる🌱
list doneで完了だけ表示✅list todoで未完了だけ表示⬜
(ヒント:Controllerで引数を読み取って、Model側に“取得メソッド”を増やす…でもOK👌)
演習B:help の表示をもう少し優しくする🌸
- 例:「まずは list してみよ〜📋✨」みたいな一言を追加💬
章末チェック(3問)🧠✨
- Controllerの役目を一言でいうと?(自分の言葉でOK🙆♀️)
- 「タイトル空欄NG」は、Controller / View / Model どこに置くのが自然?📦
listのとき Controller は具体的に何をしてる?(3ステップで)🚦
次の第7章では、done 2 みたいに 操作→更新→再表示 のループを回して「MVCが回ってる感」🌀✨を掴みにいくよ〜!