【C#入門講座】基礎からオブジェクト指向までわかりやすく解説

当ページのリンクには広告が含まれています。
目次

はじめに

近年、プログラミングは誰にとっても身近なスキルになりつつあります。
副業やキャリアアップ、趣味のアプリ開発など、学ぶ目的は人それぞれですが、その中でも注目を集めているのが C#(シーシャープ) です。

C#はMicrosoftが開発したモダンなプログラミング言語で、以下のような幅広い分野に対応しています:

  • Windowsデスクトップアプリ
  • Webアプリ(ASP.NET)
  • ゲーム開発(Unity)
  • モバイルアプリ(Xamarin、.NET MAUI)

特にUnityとの相性が良いため、「ゲームを作ってみたい!」という人にも人気があります。

コッコ隊長

コッコ隊長もUnityでゲーム開発をするためにC#を勉強しました。

さらにC#は、オブジェクト指向強い型付けといった特徴を持ち、初心者にも扱いやすい一方で、実務レベルでも通用する本格的な言語でもあります。

コッコ隊長

実務でもWindowsアプリはC#が使われることが多いですね。
でも処理速度が要求される場面ではC++が使われます。
GUI部分はC#、複雑な処理はC++というハイブリッド実装もよくあります。

とはいえ、最初は誰でも不安です。

「まったくの未経験だけど、プログラミングを始めても大丈夫?」
「クラスとかメソッドって、なに?」
「どうやって学習を進めればいいの?」

こんな疑問や不安を感じている方も多いのではないでしょうか?

本記事のゴール

本記事では、完全初心者でも安心して学べるC#入門講座として、以下のステップで解説していきます:

  • 開発環境の準備(Visual Studioの使い方)
  • C#の基本構文とデータ型
  • 条件分岐・ループなどの制御構文
  • メソッドと配列の使い方
  • クラスとオブジェクト指向の基本
  • 簡単なアプリケーション開発の実践

各章では、ただ文法を紹介するだけではなく、

  • なぜその書き方をするのか?
  • どんな場面で使えるのか?

といった「実務で役立つ視点」も取り入れています。

一緒にC#をはじめましょう

この記事を通じて、C#の基礎をしっかりと身につけることができ、
次のステップ(GUIアプリ開発やWebアプリ開発)へ進むための土台が作れるはずです。

コッコ隊長

C#の世界へ、レッツゴー!!

C#の基礎知識と開発環境の準備

C#とは?特徴と歴史

C#は、Microsoftが2000年に発表したオブジェクト指向型のプログラミング言語です。
CやC++の影響を受けつつ、Javaに近い構文を持ち、安全性と開発効率を両立できるのが大きな魅力です。

この言語は、.NET Frameworkを起点に、現在では.NET Core~.NET 6以降の「統合.NET」として進化し、さまざまなプラットフォームで動作するようになりました。

🔍 C#の主な特徴

特徴説明
オブジェクト指向クラス、継承、ポリモーフィズムなど、OOP(オブジェクト指向)の基本を網羅
ガベージコレクションメモリ管理を自動化し、メモリリークの心配を軽減
強い型付け静的型チェックにより、実行前に多くのエラーを検出可能
豊富なライブラリ.NETライブラリを標準で利用でき、日常的な開発タスクを簡略化
クロスプラットフォーム.NET 6以降は、WindowsだけでなくLinuxやmacOSにも対応

また、Visual Studioとの連携が抜群で、コード補完、デバッグ、GUI設計までオールインワンで対応できる開発環境も、初心者にとって心強いポイントです。

C#が活用される分野と用途

C#は非常に汎用性が高く、さまざまな開発分野に対応しています。
以下はC#が活躍している代表的な用途です。

💻 Windowsアプリケーション

C#は、WPF(Windows Presentation Foundation)やWinFormsを使った業務用デスクトップアプリ開発に最適です。
特に企業向けツールや社内システムなど、UIと安定性が求められる場面で広く使われています。

🌐 Webアプリケーション

ASP.NET Coreを利用することで、モダンで高速なWebアプリをC#で構築可能です。
C#だけでフロントエンドとバックエンドが統合されたWeb開発ができるのも大きな魅力です。

📱 モバイルアプリ開発

Xamarin(現在の.NET MAUI)を使えば、iOS・Android両対応のクロスプラットフォームアプリをC#で開発できます。ネイティブパフォーマンスを確保しつつ、共通コードで効率的にアプリが作れるのが特徴です。

🎮 ゲーム開発

世界的に人気のゲームエンジンUnityが、C#を主要スクリプト言語として採用しています。
スマホゲームからPC・コンソール向けまで、あらゆる規模のゲーム開発にC#が使われています

☁️ クラウド・IoT分野

MicrosoftのクラウドプラットフォームAzureとの親和性が高く、
IoTデバイスの制御やクラウドサービスの構築にもC#は活用されています。

💡 初心者にこそおすすめできる言語

これだけ幅広い分野に応用できる言語は多くありません。
C#は「ひとつの言語でいろんな開発をしてみたい!」という方にとって、非常にコストパフォーマンスの高い選択肢です。

C#を始めるための開発環境の準備

C#を学ぶ第一歩として、開発環境の構築が必要です。
ここでは、Microsoft公式の統合開発環境(IDE)であるVisual Studioのインストール方法を解説します。

Visual Studioは、C#に最適化された機能を多数備えており、補完機能・デバッグ・GUIデザインなど、初心者にも心強いツールです。

STEP
Visual Studioのダウンロード

まずは以下のURLから、Visual Studioのインストーラーを取得しましょう:

👉 Visual Studio ダウンロードページ(公式)

  • Visual Studio Community」を選択(個人・学習用途なら無料で利用できます)
  • ダウンロード後、インストーラーを実行します
STEP
必要なワークロードの選択

インストーラーを起動すると、「ワークロード(開発目的に応じた機能セット)」を選ぶ画面が表示されます。
C#学習者におすすめのワークロードは以下のとおりです:

  • .NET デスクトップ開発
     → WindowsアプリやWPF/WinFormsを作成したい方向け
  • ASP.NETおよびWeb開発
     → WebアプリやAPI開発に興味がある方はこちらも選択
  • ユニバーサル Windows プラットフォーム開発(任意)
     → UWPアプリに挑戦する場合のみ必要

ワークロードは後から追加変更できるため、最初は必要なものだけでOKです。

STEP
インストールと初期設定
  1. ワークロードを選択後、「インストール」をクリックしてインストールを開始
  2. 完了したらVisual Studioを起動し、Microsoftアカウントでサインイン(スキップも可能)
  3. 初回起動時に以下のような設定が求められます:
    • テーマの選択(ダーク・ライトなど)
    • キーバインド(ショートカット操作)の選択(例:Visual Studio、ReSharper、VSCode風)

特にこだわりがなければ、すべて「デフォルト設定」で進めて問題ありません。

💡 補足:Visual Studio CodeでもC#は可能?

Visual Studio Code(VSCode)でもC#開発は可能だけど、初心者には機能が豊富なVisual Studioの方が断然おすすめです。特にGUIアプリやASP.NETのような複雑なプロジェクトでは、Visual Studioのほうが圧倒的に使いやすいです。

最初のC#プログラムを書いてみよう

開発環境(Visual Studio)の準備が整ったら、さっそくC#の「Hello, World!」プログラムを作ってみましょう。
これは、どの言語でも最初に学ぶ「基本の1歩」です。

STEP
新しいコンソールアプリの作成

まずはVisual Studioを起動し、以下の手順でプロジェクトを作成します:

  1. [新しいプロジェクトの作成] を選択
  2. プロジェクトテンプレートから
     ⇒ 「コンソール アプリ(.NET Core または .NET 6/7)」を選択
  3. 任意のプロジェクト名(例:HelloWorldApp)と保存場所を指定し、「作成」をクリック

補足: .NET Framework ではなく .NET 6 以降 を選ぶことで、よりモダンな環境が使えます。

STEP
コードを確認・編集しよう

プロジェクトを作成すると、自動的に以下のようなコードが表示されているはずです:

  • .NET5以前の場合:
using System;

namespace HelloWorldApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, World!");
        }
    }
}
  • .NET6以降の場合:
Console.WriteLine("Hello, World!");

このコードは、コンソールに「Hello, World!」と表示するだけの超シンプルなプログラムです。

Console.WriteLine() は、文字列をターミナルに出力する命令です。
今後も頻繁に使うので、しっかり覚えておきましょう!

STEP
プログラムを実行する

コードが確認できたら、さっそく実行してみましょう:

  1. 画面上部にある「▷」ボタン(デバッグなしで開始ボタン)をクリック
  2. 下部のターミナル(出力ウィンドウ)に Hello, World! と表示されれば成功!
コッコ隊長

初めて「自分のコードが動いた瞬間」は、やっぱりうれしいですよね!

🎉 これでC#の第一歩は完了!

たったこれだけのステップで、自分だけのC#プログラムを実行できる環境が整いました。
次は、「文字列の出力」以外にもできることをどんどん学んでいきましょう。

C#の基本構文とデータ型

C#の基本文法

C#でプログラムを書くうえで、まず最初に理解しておくべきなのが文法の基本ルールです。
これをおろそかにすると、エラーが頻発し「なぜ動かないのか?」でつまずきやすくなります。
ここでは、セミコロン・インデント・コメント・波かっこ・命名規則といった、C#の書き方の土台をしっかり解説します。

セミコロン; の役割

C#では、1つの文(ステートメント)の終わりに必ずセミコロン ; を付ける必要があります。

int number = 10;
Console.WriteLine(number); // OK

セミコロンは「この行で処理が完了した」とコンパイラに伝える記号です。
もし忘れると、次のようにコンパイルエラーになります。

int number = 10  // セミコロンなし
Console.WriteLine(number); // ❌ エラーが発生

エラーの多くは“うっかりセミコロン忘れ”が原因だったりします。癖づけておきましょう!

インデント(字下げ)の使い方

C#では、Pythonのようにインデントが文法上の意味を持つわけではありません。
しかし、インデントは読みやすいコードを作るための必須習慣です。

if (number > 0)
{
    Console.WriteLine("正の数です");
}

このように、コードブロック{}の中をスペースやタブで一段下げるのがC#の一般的なスタイルです。

チーム開発でもインデントが整っているコードは理解しやすく、保守もしやすくなります。

コメントの書き方

コメントは、コードに説明を付けるための文で、プログラムの実行には影響しません。
自分や他の開発者が後で見たときに、何を意図したコードなのかが分かるようにするために使います。

  • 一行コメント
// これは1行コメントです
int age = 30; // このように行末にも書けます
  • 複数行コメント(ブロックコメント)
/*
これは
複数行にわたる
コメントです
*/

コメントは「読めばわかる単純なコード」には不要ですが、初心者のうち(勉強用のコードに対して)は積極的に書いてOK!

波かっこ{} とブロック構文

C#では、複数の処理をまとめるときに波かっこ{} を使います
たとえば、if文やforループなどでブロック化が必要です。

if (age >= 18)
{
    Console.WriteLine("成人です");
    Console.WriteLine("お酒が飲めます");
}

1行しか書かない場合でも、波かっこ {} を省略せず書くようにしましょう。
バグの混入や将来の変更ミスを防ぐのに役立ちます。

C#における命名規則(ネーミングルール)

コードの読みやすさと保守性を高めるために、一貫した命名規則を守ることは非常に重要です。
C#では以下のようなスタイルが一般的です:

要素命名スタイル
クラス名・メソッド名パスカルケース(PascalCase)MyClass, CalculateTotal
変数名・引数名キャメルケース(camelCase)userName, totalAmount

これらのルールに従うことで、他のC#開発者ともスムーズにコードを共有できるようになります。

変数とデータ型の使い方

変数とは?プログラムの“記憶箱”

C#では、値を扱うために変数(variable)を使用します。
変数とは「一時的に値を保存しておくための名前付きの箱」と考えるとわかりやすいでしょう。

静的型付けと変数の宣言

C#は静的型付け言語なので、変数を使うには明確なデータ型(型情報)を指定してから使います。

int number = 10;
string name = "Taro";
bool isActive = true;
  • int number = 10; → 整数型 int の変数 number10 を代入
  • string name = "Taro"; → 文字列型 string の変数 name"Taro" を代入
  • bool isActive = true; → 真偽値型 bool の変数 isActivetrue を代入

基本的なデータ型と使用例

  • 整数型(int, longなど)

整数(小数を含まない数値)を扱うためのデータ型です。

型名ビット数符号最小値最大値
sbyte8bitあり-128127
byte8bitなし0255
short16bitあり-32,76832,767
ushort16bitなし065,535
int32bitあり-2,147,483,6482,147,483,647
uint32bitなし04,294,967,295
long64bitあり-9京2233兆…+9京2233兆…
ulong64bitなし0約18京

使用例:

int age = 30;
long population = 7800000000;

通常は int を使えばOK。
uintulong は、マイナスを絶対に扱わないケースにのみ限定的に使用します。

  • 浮動小数点型(float, double, decimal)

小数を含む「実数」を扱うデータ型です。

型名ビット数精度(有効桁)主な用途
float32bit約7桁軽量な小数計算
double64bit約15~16桁通常の小数計算
decimal128bit約28~29桁金額や精度が必要な場面

使用例:

float pi = 3.14f;            // ← float は "f" が必要
double temperature = 36.6;
decimal price = 1999.99m;    // ← decimal は "m" が必要

金額計算には decimal を使うのがベストです。floatdouble は誤差が出やすいため注意。

  • 文字型・文字列型(char, string)

文字やテキストを扱うための型です。

型名説明使用方法
char単一の文字(UTF-16)シングルクォーテーションで囲む
string複数の文字列ダブルクォーテーションで囲む

使用例:

char initial = 'A';
string message = "こんにちは、世界!";

charstring のクォーテーションは異なるので注意。

  • 真偽値型(bool)

true(真)または false(偽)の2値を扱います。
主に条件分岐の判定や状態フラグとして使われます。

bool isRunning = false;

補足知識:varによる型推論

C#では、var キーワードを使って型を省略し、コンパイラに推論させることが可能です。

var count = 100;        // int として推論される
var title = "入門講座";  // string として推論される
var flag = true;        // bool として推論される

注意:var初期値と同時に宣言する場合にのみ使えます。

var num; // ❌ エラー:型がわからない

可読性の観点から、型が明確な場面だけに使うのがおすすめです。

変数の再代入

変数の値はあとから変更(再代入)可能です。

int score = 80;
score = 90;

定数(変更不可の変数)

const を使うと、再代入できない定数を宣言できます。

const double Pi = 3.14159;
// Pi = 3.14; // ❌ エラー

複数の変数を一括宣言する

同じデータ型の変数は、カンマ区切りで同時に宣言できます。

int x = 1, y = 2, z = 3;

Visual Studioの便利機能(型の確認と補完

  • マウスカーソルを変数や型に合わせると、型情報や説明がツールチップで表示
  • インテリセンス(入力補完機能)により、候補一覧から選ぶだけで入力可能
  • 初心者でもタイポや構文ミスを防ぎやすく、効率的にコーディングできます
コッコ隊長

エディターが高性能になって、すごく便利になったね!
ひと昔前は全部手打ちだったよ。

演算子と式の基本

演算子とは?

C#では、数値の計算・文字列の結合・条件判断などを行うために「演算子(operator)」を使います。
演算子は、あらゆる処理の中核であり、式(expression)の構成要素としても重要です。

ここでは、C#でよく使う基本的な演算子とその使い方を、順を追って解説します。

算術演算子(+ – * / %)

数値を扱う際に使用する、基本の「四則演算+剰余」の演算子です。

演算子説明使用例
+加算a + b
-減算a - b
*乗算a * b
/除算a / b
%剰余(余り)a % b
int a = 15;
int b = 4;

int sum = a + b;     // 19
int diff = a - b;    // 11
int prod = a * b;    // 60
int div = a / b;     // 3(小数点以下は切り捨て)
int mod = a % b;     // 3

Console.WriteLine($"合計: {sum}, 差: {diff}, 積: {prod}, 商: {div}, 余り: {mod}");
実行結果

合計: 19, 差: 11, 積: 60, 商: 3, 余り: 3

整数同士の割り算では小数点以下が切り捨てられる点に注意!

代入演算子(=、+=、-= など)

変数に値を代入するときに使う演算子です。
複合代入演算子を使えば、より短く記述できます。

演算子説明使用例同等の意味
=単純代入x = 10
+=加算して代入x += 2x = x + 2
-=減算して代入x -= 1x = x - 1
*=乗算して代入x *= 3x = x * 3
/=除算して代入x /= 2x = x / 2
%=剰余を代入x %= 3x = x % 3

比較演算子(==、!=、>、<、>=、<=)

2つの値を比較して真偽値(true/false)を返す演算子です。

演算子説明使用例
==等しいx == y
!=等しくないx != y
>より大きいx > y
<より小さいx < y
>=以上x >= y
<=以下x <= y
int score = 85;
bool passed = score >= 70;
Console.WriteLine($"合格か? {passed}"); // 出力: 合格か? True
実行結果

合格か? True

論理演算子(&&、||、!)

条件を組み合わせたり否定したりする演算子です。
if文などで複雑な条件判定をするときによく使います。

演算子説明意味
&&AND(かつ)x > 0 && y > 0両方がtrueのときtrue
||OR(または)x > 0 || y > 0どちらかがtrueのときtrue
!NOT(否定)!isActiveisActiveがfalseならtrue
int age = 25;
bool isMember = true;

if (age >= 18 && isMember)
{
    Console.WriteLine("大人の会員です");
}
実行結果

大人の会員です

インクリメント・デクリメント演算子(++、–)

変数の値を1だけ増減させる省略記法です。

演算子説明使用例意味
++1加算x++x = x + 1
--1減算x--x = x - 1
int count = 0;
count++; // 1
count--; // 0

++x(前置)と x++(後置)では動作のタイミングが異なる点にも注意(後述)

式(expression)とは?

C#における式(expression)とは、「値を生成するコードの構成要素」です。

式は、演算子を使って構築され、1つの結果を返します
特に条件式や計算式では、演算子の優先順位やグループ化(かっこ)を意識して記述する必要があります。

演算子の優先順位(抜粋)

優先度種類
()(グループ化)(a + b) * c
単項演算子(!, ++, --!flag, x++
算術演算子(*, /, %a * b
算術演算子(+, -a + b
比較演算子(==, !=, >, <など)x >= y
論理演算子(&&, `
最低代入演算子(=など)x = y + 1

迷ったときは、かっこ () で明示的に優先順位を指定しましょう。

これでC#における演算子と式の基本はひと通りマスターできました!
この知識は、条件分岐やループ、関数設計などすべての構文の基礎となるので、しっかり身につけておきましょう。

型変換と文字列補完(string interpolation)

C#でアプリケーションを作成する際には、異なるデータ型同士の変換(型変換)や、可読性の高い文字列出力(文字列補完)が頻繁に登場します。
この章では、C#における代表的な型変換の方法と、読みやすく簡潔な出力を実現する文字列補完(String Interpolation)について解説します。

型変換の基本

  • 暗黙的型変換(Implicit Conversion)

精度の劣化がない場合、C#は自動で型変換を行ってくれます。

int i = 100;
double d = i; // int → double に自動変換
Console.WriteLine(d); // 出力:100.0

小さい型から大きい型への変換(int → double、byte → intなど)は暗黙的にOKです。

  • 明示的型変換(Explicit Conversion / キャスト)

精度が失われる可能性がある変換では、キャストによる明示的な変換が必要です。

double pi = 3.14159;
int intPi = (int)pi; // 小数点以下が切り捨てられる
Console.WriteLine(intPi); // 出力:3

キャストはデータの損失が起きる可能性があるため、用途に応じて慎重に使いましょう。

  • Convertクラスによる型変換

安全かつ多用途に使えるのが System.Convert クラスです。

string input = "123";
int num = Convert.ToInt32(input);
Console.WriteLine(num); // 出力:123

null や不正な文字列を変換しようとすると例外が発生するため、例外処理と組み合わせるのが安全です。

  • TryParseによる安全な変換

ユーザー入力のように変換できるか確実でないケースでは、TryParse() を使うのが最も安全です。

string value = "456";
if (int.TryParse(value, out int result))
{
    Console.WriteLine($"変換成功: {result}");
}
else
{
    Console.WriteLine("変換失敗");
}

TryParseは例外を出さずに変換成否を判定できるため、実用上とても重宝されます。

文字列補完(String Interpolation)

  • 基本構文(C# 6以降)

C#では、$ を使うことで、文字列の中に変数や式を埋め込むことができます

string name = "Taro";
int age = 25;
Console.WriteLine($"名前は{name}、年齢は{age}歳です。");

可読性が高く、エラーが発生しにくいため、現在では最も推奨される文字列出力の方法です。

  • 式の埋め込みも可能

文字列補完内では、四則演算やメソッドの呼び出しなども埋め込み可能です。

int a = 5, b = 3;
Console.WriteLine($"a + b = {a + b}"); // 出力:a + b = 8
  • 従来の方法
方法デメリット
+ 演算子による連結"こんにちは、" + name + "さん"変数が多いと読みにくく、バグの原因に
string.Format()string.Format("名前は{0}", name)書式がずれやすく、古いスタイル

結論:$による文字列補完が最も推奨される方法です。

書式指定子と補完の応用

文字列補完では、書式指定子を使って数値や日付の見せ方を調整することも可能です。

double price = 1234.567;
Console.WriteLine($"価格は{price:F2}円です"); // 小数点以下2桁 → 出力:価格は1234.57円です
  • 標準の書式指定子一覧
指定子説明
F固定小数点形式(Fixed-point)
N数値(Number)
C通貨(Currency)
Pパーセンテージ
E指数表記(Exponential)
D整数の桁数補正(Decimal)
X16進数表記(Hexadecimal)

条件分岐(if, else, switch)の使い方

プログラムを作成する上で、「条件によって処理を分ける」ことは非常に重要です。
C#では if 文や switch 文を使って、条件に応じた処理の分岐を柔軟に実装できます。

この章では、条件分岐の基本から、近年導入されたswitch式(C# 7以降)まで、順を追ってわかりやすく解説します。

if文の基本構文

最も基本的な条件分岐は if 文です。条件が true の場合のみ、指定した処理を実行します。

int age = 20;

if (age >= 18)
{
    Console.WriteLine("成人です");
}

if-else構文:条件に応じて別の処理を行う

if に該当しなかった場合の処理を、else で記述します。

if (age >= 18)
{
    Console.WriteLine("成人です");
}
else
{
    Console.WriteLine("未成年です");
}

else if:複数の条件を順番に評価する

複数の条件がある場合は else if を使って分岐します。
上から順に評価され、最初に true となったブロックだけが実行されます。

if (age < 13)
{
    Console.WriteLine("子供です");
}
else if (age < 18)
{
    Console.WriteLine("中高生です");
}
else
{
    Console.WriteLine("大人です");
}

条件式で使える演算子

条件式には、以下のような比較演算子論理演算子がよく使われます:

==, !=, <, >, <=, >=(比較)
&&(AND), ||(OR), !(NOT)

switch文:特定の値による分岐に最適

switch 文は、変数の値に応じて分岐処理を行うのに便利です。
複数の if-else よりも見やすく、値が固定されている場合に向いています。

int day = 3;

switch (day)
{
    case 1:
        Console.WriteLine("月曜日");
        break;
    case 2:
        Console.WriteLine("火曜日");
        break;
    case 3:
        Console.WriteLine("水曜日");
        break;
    default:
        Console.WriteLine("その他の曜日");
        break;
}
  • break の役割

case の処理を終えたら break を書くことで、それ以降の case へ処理が流れるのを防ぎます。

  • defaultelse 的な役割

どの case にも一致しなかったときの処理を記述します。

C# 7以降:switch式(switch expression)

C# 7からは、switchを式として値を返す「switch式」が導入されました。
可読性・保守性ともに高く、コードがすっきりします。

string grade = "B";

string message = grade switch
{
    "A" => "優秀です",
    "B" => "良いです",
    "C" => "可です",
    _   => "評価なし"
};

Console.WriteLine(message);

_default の代わりとなる「ワイルドカード」です。

実用例:点数に応じた成績を出力する

  • if-elseバージョン
int score = 85;

if(score >= 90) {
	Console.WriteLine("評価: A");
} else if(score >= 80) {
	Console.WriteLine("評価: B");
} else if(score >= 70) {
	Console.WriteLine("評価: C");
} else {
	Console.WriteLine("評価: D");
}
  • switch式バージョン(C# 8以降のパターンマッチング)
int score = 85;

string grade = score switch
{
	>= 90 => "A",
	>= 80 => "B",
	>= 70 => "C",
	_     => "D"
};

Console.WriteLine($"評価: {grade}");

switch式は「マッチする条件が上から順に評価される」点に注意。

ifとswitchの使い分け

比較ポイントifswitch
柔軟な条件判定◎(論理式も可能)△(定数値が中心)
可読性△(条件が多いと煩雑)◎(値で分岐する場合に明快)
使い所範囲・複雑な条件値が明確なとき(曜日・コマンド等)

繰り返し処理(for、while、foreach)

プログラムでは、「同じ処理を何度も繰り返す」場面が頻繁にあります。
たとえば:

  • リストのすべての要素にアクセスしたい
  • 条件を満たす間だけ処理を継続したい
  • ユーザーが操作するまでループを続けたい

C#ではこうした繰り返し処理のために、主に以下の3種類のループ構文を使用します:

  • for
  • while
  • foreach

この章では、それぞれの使い方・特徴を解説します。

for文:回数が決まっているときに便利

for 文は、「○回繰り返す」といった明確な回数制御がある場合に最適です。

  • 基本構文
for (初期化; 繰り返し条件; 更新処理)
{
    // 実行される処理
}
  • 例)1〜10までの数字を出力
for (int i = 1; i <= 10; i++)
{
    Console.WriteLine(i);
}
  • 例)逆順にカウント(カウントダウン)
for (int i = 10; i >= 1; i--)
{
    Console.WriteLine(i);
}

while文:条件が成り立つ間ループする

while 文は、条件が true の間、繰り返しを続ける構文です。
「繰り返しの回数が決まっていない」ときに活躍します。

  • 基本構文
while (条件)
{
    // 実行される処理
}
  • 例)カウントを0になるまで減らす
int count = 5;

while(count > 0) {
	Console.WriteLine($"残り: {count}");
	count--;
}

条件が最初から false の場合は、一度も処理されません。

do-while文:最低1回は必ず実行される

do-while 文は、処理を1回実行したあとに条件を判定する構文です。

int num = 0;

do {
	Console.WriteLine("これは1回は実行されます");
}
while(num > 0);

入力チェックやメニュー表示など、「とりあえず1回やる」処理に向いています。

foreach文:コレクションに対するループ

foreach は、配列やリストなどのコレクションの全要素を順に処理するときに最適です。

  • 基本構文
foreach (var 要素 in コレクション)
{
    // 要素を使った処理
}
  • 例)配列内のフルーツを表示
string[] fruits = { "りんご", "みかん", "バナナ" };

foreach(string fruit in fruits) {
	Console.WriteLine(fruit);
}

foreach は内部でインデックスを使用しないため、安全で読みやすいコードが書けます。

forとforeachの使い分け

条件・目的おすすめのループ文
回数が決まっているfor
インデックスを使いたいfor
配列・リストなど全要素を順に処理したいforeach
条件が成り立つ間、柔軟に繰り返したいwhile

無限ループに注意!

繰り返し条件を正しく記述しないと、無限ループになる恐れがあります。

while(true) {
	Console.WriteLine("無限ループ中…");
}

意図的な無限ループ(ゲームループや常駐処理)以外では、必ず終了条件を設けましょう。

実用例:0が入力されるまで数値を加算

int total = 0;
int input;

do {
	Console.Write("数値を入力してください(0で終了): ");
	input = int.Parse(Console.ReadLine());
	total += input;
}
while(input != 0);

Console.WriteLine($"合計: {total}");

このようなケースでは do-while を使うことで「最初の入力を必ず受け取る」という設計が自然に書けます。

ループ構文を使いこなそう

  • forカウンタ制御に便利
  • while条件ループに適している
  • do-while少なくとも1回実行したいときに使う
  • foreachコレクション全体に対する処理にベスト

breakとcontinueの使いどころ

繰り返し処理(ループ)を行う中で、「途中でループを終了したい」あるいは「特定の条件だけ処理をスキップしたい」という場面は頻繁に登場します。

そんなときに使えるのが、breakcontinue です。

この章では、それぞれの構文の使い方と、具体的な活用例や注意点を解説します。

break文:ループやswitchを途中で終了する

break は、ループまたは switch 文をその時点で終了させます。
「これ以上処理を続ける必要がない」と判断したときに使います。

  • 基本構文(for文の例)
for(int i = 0; i < 10; i++) {
	if(i == 5) {
		break;
	}
	Console.WriteLine(i);
}
実行結果

0
1
2
3
4

i == 5 になった時点で break が実行され、ループが終了します。

  • while文での使用例
int count = 0;

while(true) {
	if(count >= 3) {
		break;
	}
	Console.WriteLine($"カウント: {count}");
	count++;
}
  • switch文における break

switch 文では、case の処理を終えたあとに break を書くことで、他の case に処理が流れるのを防ぎます。

string command = "start";

switch(command)
{
case "start":
	Console.WriteLine("開始します");
	break;
case "stop":
	Console.WriteLine("停止します");
	break;
default:
	Console.WriteLine("不明なコマンドです");
	break;
}

continue文:処理をスキップして次のループへ進む

continue は、現在の繰り返し処理をスキップし、次のループへ移行します。
「特定条件のときだけ何もせずに次へ進む」といった場合に有効です。

  • 基本構文
for(int i = 1; i <= 5; i++) {
	if(i == 3) {
		continue; // i=3 の処理をスキップ
	}
	Console.WriteLine(i);
}
実行結果

1
2
4
5

breakとcontinueの使いどころまとめ

制御構文意味・効果主な用途例
breakループ・switchを即時終了条件に一致したら処理をやめたいとき
continue現在の繰り返しだけスキップ一部の条件だけ無視したいとき(除外)

実用例1:偶数のみを出力(continue

for(int i = 1; i <= 10; i++) {
	if(i % 2 != 0) {
		continue; // 奇数はスキップ
	}
	Console.WriteLine(i); // 偶数のみ表示
}

実用例2:最初の3の倍数を見つけたら終了(break

int[] numbers = { 1, 4, 7, 9, 12, 15 };

foreach(int n in numbers) {
	if(n % 3 == 0) {
		Console.WriteLine($"最初の3の倍数: {n}");
		break;
	}
}

ネスト(入れ子)ループと break

break は、最も内側のループのみを抜けます。

for(int i = 0; i < 3; i++) {
	for(int j = 0; j < 3; j++) {
		if(j == 1) {
			break; // jループだけ終了
		}
		Console.WriteLine($"i={i}, j={j}");
	}
}
実行結果

i=0, j=0
i=1, j=0
i=2, j=0

外側のループも終了したいとき(gotoの使用:上級者向け)

外側のループも含めて一気に抜けたい場合は goto を使う方法もありますが、可読性が低下するため非推奨です。

for(int i = 0; i < 3; i++) {
	for(int j = 0; j < 3; j++) {
		if(i + j > 2) {
			goto EndLoops;
		}
		Console.WriteLine($"i={i}, j={j}");
	}
}
EndLoops:
Console.WriteLine("ループ終了");

breakとcontinueでループ制御を自在に

  • break
    ループを途中で終了したいとき
  • continue
    特定の条件をスキップしたいとき

乱用はコードの可読性を下げるので、明確な意図と共に使うのが大切です。

try-catchによる例外処理

例外処理とは?

プログラムの実行中、ユーザーの入力ミスやファイルの読み込み失敗など、予期しないエラー(例外)が発生することは避けられません。
C#では、こうした実行時エラーを「例外(Exception)」として検知し、安全に処理を継続するための仕組みとして try-catch 文が用意されています。

基本構文:try-catch

try
{
    // 例外が発生する可能性のある処理
}
catch (Exception e)
{
    // 例外が発生したときの処理
}

実用例:0での除算を例外処理で回避

int a = 10;
int b = 0;

try {
	int result = a / b;
	Console.WriteLine(result);
}
catch(DivideByZeroException e) {
	Console.WriteLine("エラー: 0で割ることはできません。");
	Console.WriteLine($"詳細: {e.Message}");
}
実行結果

エラー: 0で割ることはできません。
詳細: Attempted to divide by zero.

try ブロックでエラーが発生した場合のみ、対応する catch ブロックが実行されます。

よく使われる例外クラスと発生条件

例外クラス名主な発生条件
DivideByZeroException0で除算したとき
FormatException不正な書式の変換(文字列⇒数値など)
NullReferenceExceptionnull な変数のメンバーにアクセスしたとき
FileNotFoundException存在しないファイルへアクセスしたとき

複数のcatchで例外を分類して処理する

try {
	string input = Console.ReadLine();
	int value = int.Parse(input);
	int result = 100 / value;
	Console.WriteLine(result);
}
catch(FormatException) {
	Console.WriteLine("入力形式が正しくありません。");
}
catch(DivideByZeroException) {
	Console.WriteLine("0では割れません。");
}
catch(Exception e) {
	Console.WriteLine($"予期しないエラー: {e.Message}");
}

一般的には、具体的な例外を先に、汎用的な Exception を最後に書くのがセオリーです。

finallyブロック:最後に必ず実行される処理

finally ブロックは、例外が発生してもしなくても必ず実行されます。
リソースの解放やログ出力などに使います。

try {
	Console.WriteLine("処理開始");
}
catch {
	Console.WriteLine("例外が発生しました。");
}
finally {
	Console.WriteLine("終了処理を実行します。");
}

Exceptionクラスの情報を活用する

Exception オブジェクトは以下のような情報を持ちます:

プロパティ説明
Messageエラーメッセージ
StackTraceエラーが発生した場所のスタックトレース
InnerExceptionネストされた例外(原因となった例外)
catch (Exception ex)
{
    Console.WriteLine($"エラー内容: {ex.Message}");
    Console.WriteLine($"発生場所: {ex.StackTrace}");
}

意図的に例外を発生させる(throw)

throw を使えば、ビジネスロジック上の異常を明示的にエラーとして扱えます。

int age = -5;

if(age < 0) {
	throw new ArgumentException("年齢は0以上でなければなりません。");
}

実用例:ユーザー入力を安全に数値変換

Console.Write("年齢を入力してください: ");
string input = Console.ReadLine();

try {
	int age = int.Parse(input);
	Console.WriteLine($"あなたの年齢は {age} 歳です。");
}
catch(FormatException) {
	Console.WriteLine("数値を入力してください。");
}

このように、例外処理を入れることで、クラッシュせずにユーザーにフィードバックを返せます。

例外処理の設計指針

ポイント説明
空の catch {} はNGエラーの原因がわからなくなります。最低でも Message をログ出力
不要な try-catch は避ける発生しうる箇所に絞って使うのが鉄則
共通処理は関数化やログ機構で整理同じ例外処理を複数箇所に書かず、責任範囲でまとめる

try-catchで安定したコードを書くために

  • try-catch を使えば、プログラムが落ちずに適切に対処可能
  • エラーの種類に応じて catch を複数使い分ける
  • finallythrow も活用すれば、信頼性の高いエラーハンドリングができる

メソッドと配列の基礎

メソッドの定義と呼び出し方

メソッドとは?

メソッド(method)とは、処理をひとまとめにして名前をつけたものです。
「何度も使う処理」や「意味のまとまりを持った処理」を整理し、コードを再利用しやすく、見通しよくするために使います。

メソッドの基本構文

戻り値の型 メソッド名(引数の型 引数名, ...)
{
	// 実行する処理
	return 戻り値;
}
  • 例:2つの数値を加算するメソッド
int Add(int a, int b)
{
	return a + b;
}

戻り値がないメソッド(void

void SayHello()
{
	Console.WriteLine("こんにちは!");
}
  • void は「戻り値なし」を意味します。
  • 単に処理を実行するだけで、値を返さないときに使用します。

メソッドの呼び出し方法

メソッドは、Main メソッドや他のメソッドの中から呼び出します。

static void Main(string[] args)
{
	SayHello(); // メソッドの呼び出し
}

引数と戻り値を持つメソッド

  • 例:数値の2乗を返すメソッド
int Square(int number)
{
	return number * number;
}

int result = Square(5); // 25
Console.WriteLine(result);

複数の引数を持つメソッド

string FullName(string firstName, string lastName)
{
	return firstName + " " + lastName;
}

Console.WriteLine(FullName("Taro", "Yamada")); // 出力:Taro Yamada

戻り値なしのメソッド + 引数あり

void Greet(string name)
{
	Console.WriteLine($"こんにちは、{name}さん!");
}

Greet("Hanako"); // 出力:こんにちは、Hanakoさん!

メソッドのオーバーロード(Overload)

C#では、同じ名前のメソッドでも、引数の数や型が異なれば定義可能です。これをオーバーロードと呼びます。

class Calculator {
	static void Main(string[] args)
	{
	}

	// 2つの整数を加算
	public int Add(int a, int b)
	{
		return a + b;
	}

	// 3つの整数を加算(引数の数が違う)
	public int Add(int a, int b, int c)
	{
		return a + b + c;
	}

	// 2つの小数を加算(引数の型が違う)
	public double Add(double a, double b)
	{
		return a + b;
	}
}

呼び出し時の引数の型によって、自動的に適切なメソッドが選ばれます。

メソッド設計のポイント

ポイント説明
動詞で命名するCalculate, Display, PrintMessage など
DRY原則を守る同じ処理は繰り返さずメソッド化
単一責任にする1メソッド = 1つの目的に集中させる(単一責任の原則)
長くなりすぎない複雑な処理は分割して整理する

実用例:配列の合計と平均を求めるメソッド

int Sum(int[] numbers)
{
	int total = 0;
	foreach(int n in numbers) {
		total += n;
	}
	return total;
}

double Average(int[] numbers)
{
	return (double)Sum(numbers) / numbers.Length;
}

int[] data = { 10, 20, 30, 40 };

Console.WriteLine($"合計: {Sum(data)}");     // 合計: 100
Console.WriteLine($"平均: {Average(data)}"); // 平均: 25

配列処理を別々のメソッドに分けることで、可読性と再利用性の高いコードになります。

メソッドはC#の基本設計単位

  • 共通処理をまとめて再利用できるのがメソッドの強み
  • 引数・戻り値を適切に設計すれば、柔軟なプログラム構築が可能
  • オーバーロード・void・配列引数などを使いこなすことで表現力がアップ

引数と戻り値の型について

なぜ引数と戻り値の型が重要なのか?

C#は静的型付け言語であり、メソッドの引数や戻り値の型を明確に定義することが求められます。
これにより、安全で予測可能なコードを書くことができ、実行前に多くのエラーを防止できます。

引数の型と渡し方

  • 基本:引数には必ず型を指定する
void PrintMessage(string message)
{
	Console.WriteLine(message);
}

string 型の message を引数として受け取り、画面に出力します。

値渡し(Pass by Value)と参照渡し(Pass by Reference)

  • 値渡し(既定)

引数の値のコピーが渡され、元の変数には影響を与えません。

void Increment(int x)
{
	x++;
}

int num = 10;
Increment(num);
Console.WriteLine(num); // → 出力:10(変更されない)
  • 参照渡し(ref / out

元の変数を直接操作するには、refout を使います。
ref:呼び出し前に変数の初期化が必要
out:メソッド内で必ず代入される必要あり

void Increment(ref int x)
{
	x++;
}

int num = 10;
Increment(ref num);
Console.WriteLine(num); // → 出力:11(呼び出し元にも反映)
void Initialize(out int x)
{
	x = 100;
}

引数の高度な使い方

  • デフォルト引数(optional parameters)

引数に初期値を設定することで、省略可能になります。

void Greet(string name = "ゲスト")
{
	Console.WriteLine($"こんにちは、{name}さん!");
}

Greet();          // → こんにちは、ゲストさん!
Greet("花子");    // → こんにちは、花子さん!
  • 可変長引数(params

不定数の引数を配列として受け取ることができます。

void PrintNumbers(params int[] numbers)
{
	foreach(int n in numbers) {
		Console.Write($"{n} ");
	}
	Console.WriteLine();
}

PrintNumbers(1, 2, 3, 4); // → 1 2 3 4

戻り値の型と複数の戻り値

  • 戻り値の基本

任意の型を返すことができます。
戻り値がない場合は void を使用します。

int Double(int x)
{
	return x * 2;
}

複数の値を返したいときの方法

  • 方法①:out パラメータを使う
void GetStats(int[] data, out int min, out int max)
{
	min = data.Min();
	max = data.Max();
}

int[] values = { 10, 20, 5, 40 };
GetStats(values, out int min, out int max);
Console.WriteLine($"最小: {min}, 最大: {max}");
  • 方法②:タプル(Tuple)を使う(C# 7以降)
(int min, int max) GetStats(int[] data)
{
	return (data.Min(), data.Max());
}

var (minValue, maxValue) = GetStats(new[] { 1, 2, 3 });
Console.WriteLine($"最小: {minValue}, 最大: {maxValue}");

見やすく・書きやすく・拡張性も高い方法として、タプルの活用が推奨されます。

汎用メソッド:ジェネリック(Generics)

  • 型に依存しない柔軟なメソッドを定義する

T はジェネリック型のパラメータであり、呼び出し時に型が自動推論されます。

T GetFirst<T>(T[] array)
{
	return array[0];
}

Console.WriteLine(GetFirst(new[] { 1, 2, 3 }));    // Tはintに
Console.WriteLine(GetFirst(new[] { "a", "b" }));  // Tはstringに

実用例:ユーザー情報を処理するメソッド

(string fullName, int birthYear) GetUserInfo(string firstName, string lastName, int age)
{
	string name = $"{firstName} {lastName}";
	int year = DateTime.Now.Year - age;
	return (name, year);
}

var (name, year) = GetUserInfo("太郎", "山田", 30);
Console.WriteLine($"名前: {name}, 生年: {year}");

型の活用で安全性と柔軟性を両立しよう

  • すべての引数と戻り値には型が必要(C#は静的型付け)
  • 値渡しと参照渡しの違いを理解して使い分ける
  • 複数の戻り値には タプルか out を活用
  • 汎用的な処理にはジェネリックメソッドが強力
  • 適切な型指定により、バグの予防とコードの明確化が実現

配列とリストの扱い方

プログラムで複数のデータを一括で管理・操作するには、「配列(Array)」や「リスト(List)」のようなコレクション型が欠かせません。

どちらも「データの集合体」ですが、用途や機能には明確な違いがあります。

配列(Array)の基本

  • 特徴
    • 固定長:サイズは最初に決めて変更できない
    • 同一型の要素のみを格納
    • 処理が高速(メモリ効率も高い)
  • 宣言と初期化
int[] numbers = new int[3];     // 長さ3の配列を作成
numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;

// 初期値付きの宣言
int[] scores = { 80, 90, 75 };
  • 要素へのアクセスと長さ取得
Console.WriteLine(scores[1]);        // 出力:90
Console.WriteLine(scores.Length);    // 出力:3
  • 配列の繰り返し処理
// forループ
for(int i = 0; i < scores.Length; i++) {
	Console.WriteLine(scores[i]);
}

// foreachループ
foreach(int score in scores) {
	Console.WriteLine(score);
}
  • 多次元配列(2次元配列)
int[,] matrix = {
	{ 1, 2 },
	{ 3, 4 },
	{ 5, 6 }
};

Console.WriteLine(matrix[1, 1]); // 出力:4
  • 配列の欠点
問題点説明
サイズが固定動的に要素数を変えられない
要素追加/削除が面倒手動でコピーや新しい配列を作成する必要がある

この課題を解決するのが、可変長の List<T> です。

リスト(List)の基本

  • 特徴
    • サイズ可変:要素の追加・削除が簡単
    • 豊富なメソッドと柔軟性
    • System.Collections.GenericList<T> を使用
List<string> names = new List<string>();
names.Add("Taro");
names.Add("Hanako");
  • 主な操作メソッド一覧
メソッド/プロパティ説明
Add(item)要素の追加
Insert(index, item)指定位置に挿入
Remove(item)該当要素を削除
RemoveAt(index)指定位置の要素を削除
Clear()全要素削除
Count要素数の取得(※Lengthではない)
  • 使用例
List<int> numbers = new List<int> { 10, 20, 30 };

numbers.Add(40);         // → [10, 20, 30, 40]
numbers.Remove(20);      // → [10, 30, 40]
Console.WriteLine(numbers.Count); // → 3
  • リストのループ処理
foreach(int n in numbers) {
	Console.WriteLine(n);
}

配列とリストの相互変換

  • 配列 ⇒ List
int[] arr = { 1, 2, 3 };
List<int> list = new List<int>(arr);
  • List ⇒ 配列
List<int> list = new List<int>{1, 2, 3};
int[] arr = list.ToArray();

実用例:特定条件の要素を抽出

List<string> fruits = new List<string> { "Apple", "Banana", "Orange" };

foreach(string fruit in fruits) {
	if(fruit.StartsWith("B")) {
		Console.WriteLine($"Bで始まる果物: {fruit}");
	}
}

配列 vs リスト:使い分けの目安

比較項目配列(Array)リスト(List)
サイズ固定(変更不可)可変(自由に追加・削除)
機能最小限豊富な操作メソッドあり
パフォーマンス高速(メモリ効率良)やや劣る場合も(オーバーヘッド)
主な用途サイズが決まっているデータ動的に変化するデータ

読み取り専用でサイズが固定なら配列データの増減があるならリストが適しています。

メソッドと配列・リストを組み合わせたサンプル集

これまでに学習してきたメソッド配列・リストを組み合わせることで、より柔軟で再利用性の高いプログラムを作成できます。

この章では、典型的なユースケースに沿ったサンプルコードを通じて、実践的な使い方を解説します。

サンプル1:整数配列の合計を求める

int Sum(int[] numbers)
{
	int total = 0;
	foreach(int n in numbers) {
		total += n;
	}
	return total;
}

int[] values = { 10, 20, 30, 40 };
Console.WriteLine($"合計: {Sum(values)}"); // 出力: 合計: 100

配列を引数に取り、結果を返す汎用メソッドとして活用できます。

サンプル2:平均値を求める(合計メソッドを再利用)

double Average(int[] numbers)
{
	return (double)Sum(numbers) / numbers.Length;
}
Console.WriteLine($"平均: {Average(values)}"); // 出力: 平均: 25

Sum() を再利用することで、コードの重複を避けて保守性を向上させています。

サンプル3:最大値・最小値を返す(タプルを活用)

(int min, int max) GetMinMax(int[] numbers)
{
	int min = numbers[0];
	int max = numbers[0];

	foreach(int n in numbers) {
		if(n < min) min = n;
		if(n > max) max = n;
	}

	return (min, max);
}
var (minValue, maxValue) = GetMinMax(values);
Console.WriteLine($"最小: {minValue}, 最大: {maxValue}"); // 出力: 最小: 10, 最大: 40

C# 7以降のタプル構文で、複数の戻り値をわかりやすく返すことが可能です。

サンプル4:偶数だけを抽出して返す

int[] FilterEven(int[] numbers)
{
	List<int> result = new List<int>();

	foreach(int n in numbers) {
		if(n % 2 == 0) {
			result.Add(n);
		}
	}

	return result.ToArray();
}

int[] values = { 10, 11, 12, 13 };
int[] evenNumbers = FilterEven(values);

Console.WriteLine("偶数のみ:");
foreach(int n in evenNumbers) {
	Console.WriteLine(n);
}

条件に合う要素だけを配列として返す関数は、データ処理で頻出します。

サンプル5:2次元配列の出力(行列表示)

void PrintMatrix(int[,] matrix)
{
	for(int i = 0; i < matrix.GetLength(0); i++) // 行数
	{
		for(int j = 0; j < matrix.GetLength(1); j++) // 列数
		{
			Console.Write($"{matrix[i, j]} ");
		}
		Console.WriteLine();
	}
}

int[,] data = {
	{ 1, 2, 3 },
	{ 4, 5, 6 }
};

PrintMatrix(data);
// 出力:
// 1 2 3
// 4 5 6

GetLength(0)GetLength(1) を使えば、動的な行列処理にも対応可能です。

サンプル6:特定条件でリストをフィルタリング

List<string> FilterStartsWith(List<string> items, char letter)
{
	List<string> result = new List<string>();

	foreach(string item in items) {
		if(item.StartsWith(letter)) {
			result.Add(item);
		}
	}

	return result;
}

List<string> names = new List<string> { "Taro", "Hanako", "Takeshi", "Yuki" };
List<string> tNames = FilterStartsWith(names, 'T');

Console.WriteLine("Tで始まる名前:");
tNames.ForEach(name => Console.WriteLine(name));

List<T>要素の追加・削除が柔軟で、メソッドとの組み合わせにも最適です。

メソッド × コレクションでコードの質を高める

  • 配列・リストの操作は、メソッドと組み合わせることで読みやすく拡張性のあるコードに進化します。
  • 実用的な処理は「分割・抽象化・再利用」を意識することが重要です。
  • 条件抽出、集計、整形など、配列・リストを扱う共通処理はすべてメソッドで設計可能です。

クラスとオブジェクト指向プログラミングの基本

クラスとは何か?構造と使い方を理解しよう

クラスは「設計図」、オブジェクトは「実体」

C#はオブジェクト指向プログラミング(OOP)を採用した言語です。
OOPの中心にある概念が「クラス(class)」です。

  • クラス:データと処理をひとまとめにした設計図
  • オブジェクト(インスタンス):クラスから生成された具体的な実体

クラスの基本構造

class クラス名 {
	// フィールド(値の格納)
	// プロパティ(外部アクセス用)
	// コンストラクタ(初期化処理)
	// メソッド(処理や動作)
}

例:Personクラス(人を表現)

class Person {
	public string Name;
	public int Age;

	public void Greet()
	{
		Console.WriteLine($"こんにちは、私は{Name}、{Age}歳です。");
	}
}

インスタンスの生成と使用

class Program {
	static void Main(string[] args)
	{
		// Person クラスのインスタンスを生成
		Person person1 = new Person();

		// プロパティに値を代入
		person1.Name = "太郎";
		person1.Age = 25;

		// メソッドを呼び出す
		person1.Greet(); // 出力: こんにちは、私は太郎、25歳です。
	}
}

new 演算子でクラスのインスタンス(オブジェクト)を生成します。

クラスと構造体(struct)の違い

比較項目クラス(class)構造体(struct)
メモリ格納場所ヒープスタック
型の種類参照型(reference)値型(value)
継承の可否可能不可

データ量が多い・機能を持たせたいならクラスを使うのが一般的です。

フィールドとプロパティの違い

  • フィールド:データを直接保持する変数
public string name; // 外部から直接アクセス可能(推奨されない)
  • プロパティ:カプセル化されたアクセス方法(推奨)
class Student {
	private int score;  // フィールド
	public int Score  // プロパティ
	{
		get { return score; }
		set { score = value; }
	}
}

class Program
{
    static void Main(string[] args)
    {
        Student student = new Student();

        // Scoreプロパティを通して値を設定
        student.Score = 90;

        // Scoreプロパティを通して値を取得
        Console.WriteLine($"スコアは: {student.Score} 点です。");
    }
}
  • 自動実装プロパティ(簡略化構文)
public string Name { get; set; }

バッキングフィールドの定義を省略し、簡潔なデータ保持が可能です。

※プロパティの詳細については後述します。

コンストラクタ:インスタンスの初期化を行う特別なメソッド

// Car クラスは自動車のモデル名と製造年を表すシンプルなデータ構造
class Car
{
    // モデル名(例:Toyota、Hondaなど)を表すフィールド
    public string Model;

    // 製造年(例:2022年)を表すフィールド
    public int Year;

    // コンストラクタ:Carクラスのインスタンスを生成する際にモデル名と年を指定
    public Car(string model, int year)
    {
        // フィールドに引数の値を代入
        Model = model;
        Year = year;
    }
}

class Program
{
    // エントリーポイント(プログラムの開始地点)
    static void Main(string[] args)
    {
        // Carクラスのインスタンスを生成し、"Toyota", 2022 を渡す
        Car myCar = new Car("Toyota", 2022);

        // モデル名と年を表示(出力:Toyota, 2022)
        Console.WriteLine($"{myCar.Model}, {myCar.Year}");
    }
}

コンストラクタは new と同時に自動で呼び出される初期化処理です。

実用例:BankAccount クラス(銀行口座)

class BankAccount {
	public string Owner { get; set; }
	public decimal Balance { get; private set; }

	public BankAccount(string owner)
	{
		Owner = owner;
		Balance = 0;
	}

	public void Deposit(decimal amount)
	{
		Balance += amount;
	}

	public void Withdraw(decimal amount)
	{
		if(amount > Balance) {
			Console.WriteLine("残高不足です。");
		} else {
			Balance -= amount;
		}
	}

	public void ShowInfo()
	{
		Console.WriteLine($"{Owner}の残高は{Balance:C}です。");
	}
}

class Program {
	static void Main(string[] args)
	{
		// 口座を開設(オーナー名を指定)
		BankAccount account = new BankAccount("佐藤");

		// 残高を表示(初期状態)
		account.ShowInfo(); // 出力:佐藤の残高は¥0です。

		// 入金処理
		account.Deposit(5000m);
		account.ShowInfo(); // 出力:佐藤の残高は¥5,000です。

		// 出金処理(成功)
		account.Withdraw(2000m);
		account.ShowInfo(); // 出力:佐藤の残高は¥3,000です。

		// 出金処理(失敗:残高不足)
		account.Withdraw(5000m); // 出力:残高不足です。
		account.ShowInfo();      // 出力:佐藤の残高は¥3,000です。
	}
}

クラス設計のポイント

設計観点解説例
単一責任原則クラスは1つの「目的」または「責務」に集中させ、複数の役割を持たせない
情報の隠蔽(カプセル化)フィールドは private にして外部から直接アクセスさせず、public なプロパティやメソッドで制御する
初期化の明示コンストラクタで必要な初期値を受け取り、インスタンスが常に正しい状態で始まるようにする
再利用性・拡張性処理はメソッド単位で分けて設計し、変更や拡張がしやすい構造にする
コードの可読性メソッドやプロパティには意味のある名前を付け、コメントも適切に記述する

クラスはC#の中核概念

  • クラスは「データ + 処理」をまとめた再利用可能な単位
  • オブジェクト指向の基本は「カプセル化・継承・多態性(ポリモーフィズム)
  • new によって、同じ設計から複数のオブジェクトを生成可能

インスタンスとプロパティの概念

インスタンスとは?── 設計図から生まれる「具体的な実体」

クラスはあくまで設計図であり、それをもとに作られる実体(オブジェクト)がインスタンス(Instance)です。

class Person {
	public string Name;
	public int Age;

	public void Greet()
	{
		Console.WriteLine($"こんにちは、私は{Name}、{Age}歳です。");
	}
}

class Program {
	static void Main(string[] args)
	{
		Person p = new Person();
	}
}

この場合、Person クラスをもとに p というオブジェクトが生成され、p は独自の状態(データ)を持つようになります。

インスタンスはそれぞれ独立して存在する

class Program {
	static void Main(string[] args)
	{
		Person p1 = new Person();
		p1.Name = "Taro";

		Person p2 = new Person();
		p2.Name = "Hanako";

		Console.WriteLine(p1.Name); // 出力: Taro
		Console.WriteLine(p2.Name); // 出力: Hanako
	}
}

同じクラスから生成しても、各インスタンスは別のメモリ空間に存在し、状態を個別に保持します。

プロパティとは?── 外部アクセスを安全にする仕組み

プロパティ(Property)は、クラス内部のデータ(フィールド)へのアクセスを制御する仕組みです。

  • なぜプロパティを使うのか?
目的内容
アクセス制御書き込み専用・読み取り専用などに制限できる
カプセル化内部データの実装を外部に隠す(Encapsulation)
バリデーション不正な値の設定を防ぐロジックを追加できる

プロパティの基本構文と使用例

  • 通常のプロパティ(手動実装)
class Person {
	public string Name;
	private int age;
	public int Age  // プロパティの手動実装
	{
		get { return age; }
		set { age = value; }
	}

	public void Greet()
	{
		Console.WriteLine($"こんにちは、私は{Name}、{Age}歳です。");
	}
}

class Program {
	static void Main(string[] args)
	{
		Person p = new Person();
		p.Age = 30;
		Console.WriteLine(p.Age); // 出力: 30
	}
}
  • 自動実装プロパティ(Auto-Implemented)
public string Name { get; set; }

これは以下の省略記法です:

private string _name;

public string Name
{
    get => _name;
    set => _name = value;
}
  • 読み取り専用プロパティ
public int Id { get; }  // 初期化後は変更不可

public Person(int id)
{
    Id = id;
}

set を省略すると、コンストラクタでの初期設定専用プロパティになります。

  • バリデーション付きプロパティ
private int age;

public int Age
{
    get => age;
    set
    {
        if (value < 0)
            throw new ArgumentException("年齢は0以上でなければなりません。");

        age = value;
    }
}

set にロジックを入れることで、不正な代入を防止できます。

  • 初期値付きプロパティ
public string Country { get; set; } = "Japan";

new で生成された瞬間に "Japan" が初期値として設定されます。

実用例:Employeeクラスにおけるプロパティ活用

class Employee {
	public string Name { get; set; }
	public decimal Salary { get; private set; }

	public Employee(string name, decimal initialSalary)
	{
		Name = name;
		Salary = initialSalary;
	}

	public void RaiseSalary(decimal amount)
	{
		if(amount > 0) {
			Salary += amount;
		}
	}
}


class Program {
	static void Main(string[] args)
	{
		Employee emp = new Employee("Suzuki", 300000);
		emp.RaiseSalary(20000);
		Console.WriteLine($"{emp.Name}さんの給料は{emp.Salary:C}です。");
		// 出力:Suzukiさんの給料は¥320,000です。
	}
}

プロパティの使い分け早見表

目的構文例
通常の読み書きpublic string Name { get; set; }
読み取り専用public int Id { get; }
書き込みは内部のみpublic decimal Salary { get; private set; }
値の検証(バリデーション)get / set にロジックを追加
初期値の設定public string Country { get; set; } = "Japan";

インスタンスとプロパティはOOPの中核

  • インスタンスはクラスの「実体」であり、複数の状態を独立して保持できる
  • プロパティは、安全かつ柔軟にデータへアクセスするためのインターフェース
  • 適切なプロパティ設計により、保守性・拡張性・安全性の高いコードが実現可能

コンストラクタとメソッドの役割

クラス設計において、「コンストラクタ(constructor)」と「メソッド(method)」は、それぞれ異なる目的と役割を担っています。
この章では、それぞれの使いどころ・違い・実装パターン・設計上のベストプラクティスを解説します。

コンストラクタとは?— オブジェクトの「初期化専用メソッド」

コンストラクタは、オブジェクトの生成時に自動で呼び出される特殊なメソッドです。
名前はクラス名と同一で、戻り値の型は書きません。

コンストラクタの基本構文と使用例

class Person {
	public string Name;
	public int Age;

	// コンストラクタ
	public Person(string name, int age)
	{
		Name = name;
		Age = age;
	}
}

class Program {
	static void Main(string[] args)
	{
		// 使用例
		Person p = new Person("Taro", 25);
		Console.WriteLine($"{p.Name}, {p.Age}歳");
	}
}

コンストラクタの主な役割

  • フィールドやプロパティの初期化
  • 生成時に必要なデータの受け取り
  • 不完全なインスタンス生成の防止

コンストラクタのオーバーロード(複数定義)

class Product {
	public string Name { get; }
	public decimal Price { get; }

	// 名前だけ指定
	public Product(string name)
	{
		Name = name;
		Price = 0;
	}

	// 名前と価格を指定
	public Product(string name, decimal price)
	{
		Name = name;
		Price = price;
	}
}

class Program {
	static void Main(string[] args)
	{
		// 使用例
		Product p1 = new Product("りんご");
		Product p2 = new Product("みかん", 150);
	}
}

引数のパターンに応じた柔軟な初期化が可能になります。

デフォルトコンストラクタとは?

引数のないコンストラクタを「デフォルトコンストラクタ」と呼びます。
※コンストラクタの定義が無い場合、デフォルトコンストラクタは自動生成されますが、明示的にコンストラクタを定義すると、自動生成はされなくなります。

public Product()
{
    Name = "不明";
    Price = 0;
}

メソッドとは?— 振る舞い(処理)を定義する機能

メソッドは、クラスやインスタンスが持つ処理(動作)を定義する関数です。
コンストラクタとは異なり、任意のタイミングで呼び出して処理を実行します。

public void PrintInfo()
{
    Console.WriteLine($"商品名: {Name}, 価格: {Price}円");
}

コンストラクタとメソッドの違い(比較表)

項目コンストラクタメソッド
名前クラス名と同じ任意の名前
戻り値の型記述しない(戻り値なし)void または任意の型
呼び出されるタイミングオブジェクト生成時に自動任意のタイミングで明示的に呼び出し
主な役割初期化処理、必須パラメータの受け渡し振る舞い(処理)の定義

実用例:Memberクラスの設計に見る使い分け

class Member {
	public string Name { get; }
	public DateTime JoinedDate { get; }
	private int points;

	// コンストラクタ(初期化)
	public Member(string name)
	{
		Name = name;
		JoinedDate = DateTime.Now;
		points = 0;
	}

	// メソッド(動作)
	public void AddPoints(int amount)
	{
		if(amount > 0) {
			points += amount;
		}
	}

	public void ShowStatus()
	{
		Console.WriteLine($"{Name}さん、入会日: {JoinedDate.ToShortDateString()}、ポイント: {points}");
	}
}

class Program {
	static void Main(string[] args)
	{
		// 使用例
		Member m = new Member("Hanako");
		m.AddPoints(150);
		m.ShowStatus();
		// 出力例: Hanakoさん、入会日: 2025/05/01、ポイント: 150
	}
}

設計上の使い分けの指針

ポイント解説
必須の初期化はコンストラクタで行う初期値が欠けると成り立たない場合に使う
任意の動作はメソッドに分離する状況によって呼び出す必要がある処理はメソッド化
責務の分離を明確に保つ初期化と振る舞いは分けて設計すると保守性が高まる

コンストラクタとメソッドは「生成」と「振る舞い」を分ける

  • コンストラクタ
    生成と初期設定の責任を担う
  • メソッド
    オブジェクトに「動作」を与える
  • 正しく使い分けることで、意図が明確で堅牢なクラス設計が実現できる

クラス設計とオブジェクト指向の基礎

カプセル化・継承・ポリモーフィズムを理解する

C#は、本格的なオブジェクト指向プログラミング(OOP)を実践できる強力な言語です。
OOPの3本柱と呼ばれる下記の原則は、保守性・再利用性・拡張性の高い設計の要となります:

  • カプセル化(Encapsulation)
  • 継承(Inheritance)
  • ポリモーフィズム(Polymorphism)

この章では、それぞれの概念とC#での実装方法、設計への応用をわかりやすく解説します。

カプセル化(Encapsulation)

  • 概要

内部の実装を隠し、必要な操作だけ外部に公開する」設計手法です。
データ保護・誤操作の防止・仕様変更の影響抑制といった目的があります。

  • アクセス修飾子による制御
修飾子アクセス可能な範囲
publicすべてのコードからアクセス可能
private同じクラス内のみ
protected派生クラスからもアクセス可能
internal同一アセンブリ内でアクセス可能
  • カプセル化の例
class Account {
	private int balance;

	public void Deposit(int amount)
	{
		if(amount > 0) balance += amount;
	}

	public int GetBalance()
	{
		return balance;
	}
}

フィールド balanceprivate にし、安全な操作手段(メソッド)だけを公開します。

継承(Inheritance)

  • 概要

既存のクラス(親クラス)をベースに、機能を拡張・再利用できる仕組みです。
重複コードの削減、汎用的な構造の構築に役立ちます。

  • 基本構文と使用例
class Animal {
	public void Breathe()
	{
		Console.WriteLine("呼吸しています");
	}
}

class Dog : Animal {
	public void Bark()
	{
		Console.WriteLine("ワンワン!");
	}
}

class Program {
	static void Main(string[] args)
	{
		// 使用例
		Dog dog = new Dog();
		dog.Breathe(); // 継承元のメソッド
		dog.Bark();    // 派生クラスのメソッド
	}
}
  • メソッドのオーバーライド(再定義)
class Animal {
	public virtual void Speak()
	{
		Console.WriteLine("動物の鳴き声");
	}
}

class Cat : Animal {
	public override void Speak()
	{
		Console.WriteLine("ニャー");
	}
}

virtualoverride を使うことで、親の動作を子で自由に書き換え可能になります。

ポリモーフィズム(Polymorphism)

  • 概要

同じ型を通じて異なる振る舞いを実行できる」柔軟な構文。
これにより、条件分岐を排し、拡張性の高いコードが実現できます。

  • 実行例(多態性の活用)
class Animal {
	public virtual void Speak()
	{
		Console.WriteLine("動物の鳴き声");
	}
}

class Dog : Animal {
	public override void Speak()
	{
		Console.WriteLine("ワンワン!");
	}
}

class Cat : Animal {
	public override void Speak()
	{
		Console.WriteLine("ニャー");
	}
}

class Program {
	static void Main(string[] args)
	{
		List<Animal> animals = new List<Animal>
		{
			new Dog(),
			new Cat()
		};

		foreach(Animal a in animals) {
			a.Speak(); // Dog: ワンワン! Cat: ニャー(動的バインディング)
		}
	}
}

抽象クラスとインターフェース

  • 抽象クラス(abstract

概要:
共通の処理(実装)とルール(定義)を1つにまとめた“中間クラス”
インスタンス化できない
派生クラス(サブクラス)で継承して使用

特徴:

項目内容
実装を含められる可(メソッドに中身を書ける)
フィールドやコンストラクタ持てる
多重継承不可(クラスは1つしか継承できない)
インスタンス化不可(new できない)
abstract class Animal
{
    public string Name;
    public void Breathe()
    {
        Console.WriteLine("呼吸している");
    }
    public abstract void Speak(); // 派生クラスで必ず実装
}

class Dog : Animal
{
    public override void Speak()
    {
        Console.WriteLine("ワンワン!");
    }
}
  • インターフェース(interface

概要:
「できることの約束」だけを定義する契約
実装は一切書かず、すべてのメンバーが抽象的
複数のインターフェースを同時に実装可能

特徴:

項目内容
実装を含められる不可(C# 8以降、一部可能)
フィールドや状態を持てる不可
多重実装可能(複数インターフェース)
コンストラクタ持てない
interface IFlyable
{
    void Fly();
}

interface ISwimmable
{
    void Swim();
}

class Duck : IFlyable, ISwimmable
{
    public void Fly()
    {
        Console.WriteLine("空を飛ぶ");
    }

    public void Swim()
    {
        Console.WriteLine("水を泳ぐ");
    }
}

実用例:家電製品クラスにおける抽象化

abstract class Appliance {
	public string Brand { get; set; }
	public abstract void TurnOn();
}

class WashingMachine : Appliance {
	public override void TurnOn()
	{
		Console.WriteLine($"{Brand} 洗濯機を起動しました。");
	}
}

class Program {
	static void Main(string[] args)
	{
		// 使用例
		Appliance wm = new WashingMachine { Brand = "Panasonic" };
		wm.TurnOn(); // Panasonic 洗濯機を起動しました。
	}
}

設計指針:SOLID原則(OOPの中核)

項目原則名内容
S単一責任原則1クラス = 1役割に限定する
O開放/閉鎖原則拡張に開き、修正に閉じる
Lリスコフの置換原則親クラスの代替として子クラスが使えるべき
Iインターフェース分離原則不要なメソッドまで強制しない
D依存性逆転原則実装に依存せず、抽象に依存する

SOLID原則に従えば、拡張・保守に強いOOP設計が可能になります。

OOPの柱を理解してクラス設計に活かす

  • カプセル化:内部構造を隠し、安全な操作のみ公開
  • 継承:共通機能を集約し、派生クラスで再利用・拡張
  • ポリモーフィズム:型に依存せず多様な振る舞いを実行可能
  • 抽象化と契約:柔軟で堅牢なシステムの土台を築く

C#で簡単なアプリケーションを作ってみよう

コンソールアプリケーションの開発手順

ここまでで、C#の基本文法やオブジェクト指向の考え方を学んできました。
この章では、実際に手を動かしてアプリケーションを作成することで、C#の実践的な使い方を体験していきましょう。

今回は「おみくじアプリ」を例に、プロジェクトの作成からコーディング、実行までの流れを解説します。

STEP
アプリの内容を決める

今回作るのは、コンソールで動く簡易おみくじアプリです。

おみくじアプリの仕様:

  • 実行時に「Enterキーでおみくじを引く」と表示
  • ユーザーがEnterを押すと、運勢(例:大吉〜凶)をランダム表示
STEP
プロジェクトを作成する

Visual Studioでの手順:

  1. Visual Studioを起動
  2. 「新しいプロジェクトの作成」をクリック
  3. コンソール アプリ(.NET Core / .NET 6)」を選択
  4. プロジェクト名を入力(例:OmikujiApp
  5. 「作成」を押してプロジェクトを生成
STEP
プログラムの構造を確認する

Visual Studioで作成される初期テンプレートは以下のような構成です:

namespace OmikujiApp
{
    class Program
    {
        static void Main(string[] args)
        {
            // アプリの処理をここに記述
        }
    }
}
STEP
おみくじ処理を追加する

コード例:

namespace OmikujiApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("★☆ おみくじアプリ ☆★");
            Console.WriteLine("Enterキーを押しておみくじを引きましょう...");
            Console.ReadLine(); // 入力待ち

            string[] fortunes = { "大吉", "中吉", "小吉", "吉", "末吉", "凶" };
            Random rand = new Random();
            int index = rand.Next(fortunes.Length);

            string result = fortunes[index];
            Console.WriteLine($"あなたの運勢は…『{result}』です!");

            // 運勢ごとのコメントを追加
            if (result == "大吉")
            {
                Console.WriteLine("今日は何をやっても上手くいくでしょう!");
            }
            else if (result == "凶")
            {
                Console.WriteLine("今日は慎重に行動しましょう。");
            }
        }
    }
}
STEP
アプリをビルドして実行

Visual Studioでコードを書き終えたら、次の方法で実行します:

  • 「▶開始」ボタンをクリック
  • または Ctrl + F5 を押してデバッグなしで実行

実行するとコンソール画面が開き、運勢が表示されます。

STEP
ユーザー体験を向上させる工夫

より実用的・面白いアプリにするためのアイデアも紹介します:

  • 「もう一度引きますか?」の再試行ループを追加
  • 「今日の日付」とともに運勢を表示(DateTime.Now を使用)
  • 運勢ごとに異なる色で表示(Console.ForegroundColor

例)再試行の追加(ループ処理):

while (true)
{
    Console.WriteLine("\nEnterキーでおみくじを引きます(qで終了):");
    string input = Console.ReadLine();

    if (input == "q") break;

    // おみくじ処理を再実行
}

開発時の心がけ(学習効率を上げるコツ)

  • 少しずつ書いて動作確認する(エラー箇所を特定しやすくなる)
  • エラーは調べるチャンス。焦らず冷静に原因を追及
  • コメント(//)で意図を明記しながら書くと後で見返しやすい

ユーザー入力を受け取る仕組み

ユーザーの入力を受け取り、それに応じて動作を変えることは、アプリケーションにとって非常に重要な機能です。
この章では、C#のコンソールアプリケーションでのユーザー入力処理について、以下の観点から解説します:

  • 基本的な文字列入力
  • 数値への変換と安全な型チェック
  • 条件分岐(if / switch)
  • 入力の繰り返し処理
  • 入力のバリデーション(検証)

基本:文字列を取得する Console.ReadLine()

Console.Write("あなたの名前を入力してください: ");
string name = Console.ReadLine();
Console.WriteLine($"{name}さん、こんにちは!");
  • Console.ReadLine() は、入力された1行の文字列を取得します。
  • ユーザーが Enter を押すまでプログラムは待機します。

数値を入力 ⇒ 文字列から型変換(int.Parse

Console.Write("年齢を入力してください: ");
string input = Console.ReadLine();
int age = int.Parse(input);
Console.WriteLine($"あなたは{age}歳ですね。");

文字列を数値に変換する際、不正な入力があると例外が発生します(FormatException)。

安全な型変換:int.TryParse の活用

Console.Write("年齢を入力してください: ");
string input = Console.ReadLine();

if(int.TryParse(input, out int age)) {
	Console.WriteLine($"あなたは{age}歳ですね。");
} else {
	Console.WriteLine("⚠ 数字を入力してください。");
}
  • TryParse は変換の成否を true / false で返します。
  • 失敗しても例外が出ないため、ユーザー入力に対して非常に安全です。

入力に応じて動作を変える(if 分岐)

if(age < 13) {
	Console.WriteLine("こんにちは、子どもさん!");
} else if(age < 20) {
	Console.WriteLine("こんにちは、ティーンエイジャー!");
} else {
	Console.WriteLine("こんにちは、大人の方!");
}

選択肢を使った分岐:switch

Console.WriteLine("メニューを選択してください:");
Console.WriteLine("1. おみくじ");
Console.WriteLine("2. 挨拶");
Console.Write("番号を入力: ");
string choice = Console.ReadLine();

switch(choice)
{
case "1":
	Console.WriteLine("✨ 大吉です!");
	break;
case "2":
	Console.WriteLine("こんにちは!");
	break;
default:
	Console.WriteLine("⚠ 無効な選択です。");
	break;
}

入力を繰り返す:while ループ

while(true) {
	Console.Write("数字を入力してください(0で終了): ");
	string input = Console.ReadLine();

	if(int.TryParse(input, out int number)) {
		if(number == 0) break;
		Console.WriteLine($"入力された数: {number}");
	} else {
		Console.WriteLine("⚠ 数値を入力してください。");
	}
}

入力バリデーション(検証)の基本

ユーザーからの入力は、常に想定外の値が入力される可能性を考慮する必要があります。

  • よく使うチェック
チェック内容方法
空白かどうかstring.IsNullOrWhiteSpace(input)
数値かどうかint.TryParse()
範囲内かif (value >= 0 && value <= 100)
特定の形式Regex.IsMatch()(正規表現を使用)
  • 実用例:年齢に応じたメッセージ表示
Console.Write("年齢を入力してください: ");
string input = Console.ReadLine();

if(int.TryParse(input, out int age)) {
	if(age < 0) {
		Console.WriteLine("⚠ 年齢は0以上で入力してください。");
	} else if(age < 13) {
		Console.WriteLine("こんにちは、子どもさん!");
	} else if(age < 20) {
		Console.WriteLine("こんにちは、ティーンエイジャー!");
	} else {
		Console.WriteLine("こんにちは、大人の方!");
	}
} else {
	Console.WriteLine("⚠ 年齢は数字で入力してください。");
}

ユーザー入力処理の最適解

ポイント解説
例外を防ぐ入力処理TryParseを活用し、例外を回避する
入力の検証空白・範囲・形式などのチェックを行う
フィードバックの工夫ユーザーが理解しやすいメッセージを返す
必要なら繰り返し処理whiledo-while で再入力を促す

条件分岐とループを使ったミニアプリの作成

数当てゲームを通じてロジックを身につけよう

これまで学んできた if / switch などの条件分岐for / while などの繰り返し処理を組み合わせて、実践的なミニアプリケーションを作成してみましょう。
今回は、C#で「数当てゲーム」を開発し、ロジックの構築・エラーハンドリング・状態管理を体験します。

アプリの内容:数当てゲーム

  • ランダムで選ばれた「1〜100の数字」をユーザーが当てる
  • ユーザーが入力した数に対して「高すぎ」「低すぎ」などのヒントを表示
  • 正解すると、試行回数と履歴を表示してゲーム終了
STEP
プロジェクトの作成
  1. Visual Studio を起動
  2. 「新しいプロジェクト」→「コンソール アプリ(.NET 6)」を選択
  3. プロジェクト名:NumberGuessingGame
  4. 作成をクリック
STEP
基本コード(完成形)
namespace NumberGuessingGame {
	class Program {
		static void Main(string[] args)
		{
			Console.WriteLine("★☆ 数当てゲーム ☆★");
			Console.WriteLine("1~100の数字を当ててください。");

			Random rand = new Random();
			int answer = rand.Next(1, 101); // 正解の乱数
			List<int> guesses = new List<int>();
			int guess;
			int attempts = 0;

			while(true) {
				Console.Write("数字を入力してください: ");
				string input = Console.ReadLine();

				if(!int.TryParse(input, out guess)) {
					Console.WriteLine("数字を入力してください。");
					continue;
				}

				if(guess < 1 || guess > 100) {
					Console.WriteLine("1~100の範囲で入力してください。");
					continue;
				}

				guesses.Add(guess);
				attempts++;

				if(guess < answer) {
					Console.WriteLine("もっと大きい数字です。");
				} else if(guess > answer) {
					Console.WriteLine("もっと小さい数字です。");
				} else {
					Console.WriteLine($"\n正解!{attempts}回で当たりました!");
					Console.WriteLine("あなたの入力履歴: " + string.Join(", ", guesses));
					break;
				}
			}
		}
	}
}
STEP
コードの要点解説
要素解説
Random.Next(1, 101)1〜100のランダムな整数を生成
while (true)ユーザーが正解するまで無限ループ
int.TryParse安全に文字列→整数へ変換
List<int>入力された数を履歴として記録
continue無効な入力をスキップし、次のループへ
break正解時にループ終了
STEP
機能の拡張ポイント

入力履歴の表示:

Console.WriteLine("あなたの入力履歴: " + string.Join(", ", guesses));

リトライ機能(ゲームを繰り返す):

Console.Write("\nもう一度遊びますか? (y/n): ");
string again = Console.ReadLine().ToLower();
if (again == "y")
{
    // Main メソッドを再呼び出す、またはループ化する構造に変更
}

入力範囲の制限:

if (guess < 1 || guess > 100)
{
    Console.WriteLine("1〜100の範囲で入力してください。");
    continue;
}
STEP
このアプリで習得できること
  • if / else if / else による条件分岐の設計
  • whileループによる継続的な入力処理
  • TryParseによる型変換とエラーハンドリング
  • Listによるデータの蓄積と出力
  • break / continue を使ったループ制御

ロジックを「作って動かす」ことで身につける

学習ポイント実践内容
小さく作って確実に動かす最小限の構成で正常動作を確認
機能を追加しながら理解を深める履歴・バリデーション・再試行など段階的に拡張
トライ&エラーを恐れず試すエラーを通じて理解が深まる構造体験型学習

実行結果の確認と改善ポイント

作ったあとが本番。完成から振り返りまでを実践しよう

前節で完成した「数当てゲーム」を例に、動作確認の手順と、ユーザー体験(UX)を高めるための改善策について解説します。
アプリを作り終えたあとは、単なる動作確認にとどまらず、コードの見直し・操作性の向上・エラー耐性の強化など、多角的な視点で振り返ることが重要です。

実行結果を確認する方法

  • Visual Studioで実行
    1. 画面上部の ▶(開始)ボタンをクリック
    2. または Ctrl + F5デバッグなし実行
  • 想定される出力例
★☆ 数当てゲーム ☆★
1~100の数字を当ててください。
数字を入力してください: 50
もっと小さい数字です。
数字を入力してください: 25

正解!2回で当たりました!
あなたの入力履歴: 50, 25

よくある問題とその改善方法

  • 範囲外の数値が入力される
if (guess < 1 || guess > 100)
{
    Console.WriteLine("1〜100の範囲で入力してください。");
    continue;
}

改善の意義:
ユーザーが誤ってルール外の数値を入力した場合でも、適切にガイドすれば不快感を与えません。

  • 空文字や無効な文字列が入力された
if (!int.TryParse(input, out guess))
{
    Console.WriteLine("数字を入力してください。");
    continue;
}

改善の意義:
不正な入力でアプリが落ちるのを防ぎ、堅牢で安心感のあるプログラムになります。

  • ゲームのリトライ機能を追加
Console.Write("もう一度遊びますか? (y/n): ");
string again = Console.ReadLine().ToLower();

if (again == "y")
{
    // 状態を初期化して再実行
}
else if (again == "n")
{
    Console.WriteLine("ゲームを終了します。");
    break;
}
else
{
    Console.WriteLine("⚠ yかnで答えてください。");
}

改善の意義:
ゲームを再プレイしやすくすることで、体験の流れを中断せずに楽しめる設計になります。

  • 入力履歴を表示して学習を促す
Console.WriteLine("あなたの入力履歴: " + string.Join(", ", guesses));

改善の意義:
どのように答えに近づいたのかを振り返ることで、ユーザーに達成感と学習効果を提供できます。

UX(ユーザー体験)向上のためのアイデア

改善案効果・目的
正解時に Console.Beep()ゲーム性・エンタメ性の向上
名前入力を導入するよりパーソナルな体験
難易度選択を追加する幅広いプレイヤーに対応可能(Easy/Hardなど)
回数の統計を記録リプレイ性の向上とユーザーの成長支援

応用例:難易度とプレイヤー名つきゲーム(構想)

  • 難易度によって範囲を変更(例:Easy: 1〜50、Hard: 1〜200)
  • プレイヤー名を入力して挨拶と共に開始
  • 正解後に履歴・試行回数・難易度を表示

アプリは「作って終わり」ではない

フェーズ取り組むべきこと
動作確認期待通りに動くかを丁寧にチェック
不具合の修正入力例や再現条件をもとに、安定性を改善
UX視点の振り返り「ユーザーはどう感じるか」を常に意識する

成長につながる「振り返り型学習」

完成したアプリを振り返って改善することで、以下の力が育ちます:

  • コードの可読性・拡張性を意識したリファクタリング力
  • ユーザー目線で考える設計力
  • 小さな工夫でアプリの品質を大きく向上させる経験

まとめ

本講座では、C#の基本文法からオブジェクト指向、実践的なアプリ開発までを、順を追って学習してきました。
コードを「読む」「書く」「動かす」ことを通じて、C#の全体像と実用的なスキルの土台がしっかり築けたはずです。

ここでは学んだ内容を振り返りつつ、今後の学習方針についてもご案内します。

本記事で学んだこと:総まとめ

開発の基本と環境構築

  • C#の特徴と、.NETとの関係
  • Visual Studioを使った開発環境の準備
  • 最初のプログラム Hello, World! の実行

基本文法・制御構文

  • 変数とデータ型(int, string, boolなど)
  • 算術・比較・論理演算子の使い方
  • 条件分岐(if, switch)と繰り返し(for, while, foreach
  • break / continue によるループ制御
  • try-catch を使った例外処理の基礎

メソッドとデータ構造

  • メソッドの定義・呼び出し・引数と戻り値
  • 配列 / リストを使った複数データの操作
  • ロジックの再利用を目的としたメソッド化

クラスとオブジェクト指向

  • クラスとインスタンスの基本
  • プロパティとコンストラクタの使い分け
  • カプセル化・継承・ポリモーフィズムの実装例
  • 抽象クラス・インターフェースによる柔軟な設計

実践アプリの開発

  • コンソールアプリの作成手順
  • Console.ReadLine()を用いたユーザー入力とバリデーション
  • 条件分岐とループを組み合わせた「数当てゲーム」
  • 入力履歴や再挑戦機能など、UXを意識した改良

次に進むためのステップ

基礎を習得できた今こそ、実践的なテーマにチャレンジするタイミングです。以下の分野は特におすすめです。

学習テーマ内容
🖥 Windowsアプリ(WPF)GUIアプリの構築に挑戦
🌐 Webアプリ(ASP.NET Core)Web APIや動的サイトの開発
🗄 データベース連携(EF Core)データの保存・検索の自動化
🧪 テストとデバッグ単体テストやVisual Studioでの検証
🔍 LINQ(リンク)コレクションに対する強力なデータ操作

学びを定着させるために

習った内容を深く身につけるには、アウトプットと継続的な実践が欠かせません。

  • 自分のアイデアで小さなアプリを作ってみる
  • 他人にコードやロジックを説明してみる
  • GitHubに成果をアップしてポートフォリオにする
  • Microsoft LearnやC#公式ドキュメントを活用し、知識を補強

最後に

C#は一度身につければ、デスクトップアプリ、Web、ゲーム、クラウド開発まで幅広く活躍できるパワフルな言語です。
初心者であっても、正しい手順で一歩ずつ積み重ねていけば、確実に実践で通用するスキルが身につきます。

この講座が、あなたの「プログラミングの第一歩」そして「開発者としてのキャリア構築」に役立つものであったなら、心から嬉しく思います。

今後もあなたのC#ライフが、楽しく、そして実り多きものになることを願っています。
引き続き、学習を応援しています! 💻✨

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

CAPTCHA


目次