はじめに
近年、プログラミングは誰にとっても身近なスキルになりつつあります。
副業やキャリアアップ、趣味のアプリ開発など、学ぶ目的は人それぞれですが、その中でも注目を集めているのが 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デザインなど、初心者にも心強いツールです。
まずは以下のURLから、Visual Studioのインストーラーを取得しましょう:
- 「Visual Studio Community」を選択(個人・学習用途なら無料で利用できます)
- ダウンロード後、インストーラーを実行します
インストーラーを起動すると、「ワークロード(開発目的に応じた機能セット)」を選ぶ画面が表示されます。
C#学習者におすすめのワークロードは以下のとおりです:
- .NET デスクトップ開発
→ WindowsアプリやWPF/WinFormsを作成したい方向け - ASP.NETおよびWeb開発
→ WebアプリやAPI開発に興味がある方はこちらも選択 - ユニバーサル Windows プラットフォーム開発(任意)
→ UWPアプリに挑戦する場合のみ必要
- ワークロードを選択後、「インストール」をクリックしてインストールを開始
- 完了したらVisual Studioを起動し、Microsoftアカウントでサインイン(スキップも可能)
- 初回起動時に以下のような設定が求められます:
- テーマの選択(ダーク・ライトなど)
- キーバインド(ショートカット操作)の選択(例: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歩」です。
まずはVisual Studioを起動し、以下の手順でプロジェクトを作成します:
- [新しいプロジェクトの作成] を選択
- プロジェクトテンプレートから
⇒ 「コンソール アプリ(.NET Core または .NET 6/7)」を選択 - 任意のプロジェクト名(例:HelloWorldApp)と保存場所を指定し、「作成」をクリック
プロジェクトを作成すると、自動的に以下のようなコードが表示されているはずです:
- .NET5以前の場合:
using System;
namespace HelloWorldApp
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello, World!");
}
}
}
- .NET6以降の場合:
Console.WriteLine("Hello, World!");
このコードは、コンソールに「Hello, World!」と表示するだけの超シンプルなプログラムです。
コードが確認できたら、さっそく実行してみましょう:
- 画面上部にある「▷」ボタン(デバッグなしで開始ボタン)をクリック
- 下部のターミナル(出力ウィンドウ)に
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; // このように行末にも書けます
- 複数行コメント(ブロックコメント)
/*
これは
複数行にわたる
コメントです
*/
波かっこ{}
とブロック構文
C#では、複数の処理をまとめるときに波かっこ{}
を使います。
たとえば、if
文やfor
ループなどでブロック化が必要です。
if (age >= 18)
{
Console.WriteLine("成人です");
Console.WriteLine("お酒が飲めます");
}
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
の変数number
に10
を代入string name = "Taro";
→ 文字列型string
の変数name
に"Taro"
を代入bool isActive = true;
→ 真偽値型bool
の変数isActive
にtrue
を代入
基本的なデータ型と使用例
- 整数型(int, longなど)
整数(小数を含まない数値)を扱うためのデータ型です。
型名 | ビット数 | 符号 | 最小値 | 最大値 |
---|---|---|---|---|
sbyte | 8bit | あり | -128 | 127 |
byte | 8bit | なし | 0 | 255 |
short | 16bit | あり | -32,768 | 32,767 |
ushort | 16bit | なし | 0 | 65,535 |
int | 32bit | あり | -2,147,483,648 | 2,147,483,647 |
uint | 32bit | なし | 0 | 4,294,967,295 |
long | 64bit | あり | -9京2233兆… | +9京2233兆… |
ulong | 64bit | なし | 0 | 約18京 |
使用例:
int age = 30;
long population = 7800000000;
- 浮動小数点型(float, double, decimal)
小数を含む「実数」を扱うデータ型です。
型名 | ビット数 | 精度(有効桁) | 主な用途 |
---|---|---|---|
float | 32bit | 約7桁 | 軽量な小数計算 |
double | 64bit | 約15~16桁 | 通常の小数計算 |
decimal | 128bit | 約28~29桁 | 金額や精度が必要な場面 |
使用例:
float pi = 3.14f; // ← float は "f" が必要
double temperature = 36.6;
decimal price = 1999.99m; // ← decimal は "m" が必要
- 文字型・文字列型(char, string)
文字やテキストを扱うための型です。
型名 | 説明 | 使用方法 |
---|---|---|
char | 単一の文字(UTF-16) | シングルクォーテーションで囲む |
string | 複数の文字列 | ダブルクォーテーションで囲む |
使用例:
char initial = 'A';
string message = "こんにちは、世界!";
- 真偽値型(bool)
true
(真)または false
(偽)の2値を扱います。
主に条件分岐の判定や状態フラグとして使われます。
bool isRunning = false;
補足知識:varによる型推論
C#では、var
キーワードを使って型を省略し、コンパイラに推論させることが可能です。
var count = 100; // int として推論される
var title = "入門講座"; // string として推論される
var flag = true; // bool として推論される
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 += 2 | x = x + 2 |
-= | 減算して代入 | x -= 1 | x = x - 1 |
*= | 乗算して代入 | x *= 3 | x = x * 3 |
/= | 除算して代入 | x /= 2 | x = x / 2 |
%= | 剰余を代入 | x %= 3 | x = 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(否定) | !isActive | isActive が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
式(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
- 明示的型変換(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
- TryParseによる安全な変換
ユーザー入力のように変換できるか確実でないケースでは、TryParse()
を使うのが最も安全です。
string value = "456";
if (int.TryParse(value, out int result))
{
Console.WriteLine($"変換成功: {result}");
}
else
{
Console.WriteLine("変換失敗");
}
文字列補完(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) |
X | 16進数表記(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
へ処理が流れるのを防ぎます。
default
はelse
的な役割
どの case
にも一致しなかったときの処理を記述します。
C# 7以降:switch式(switch expression)
C# 7からは、switchを式として値を返す「switch式」が導入されました。
可読性・保守性ともに高く、コードがすっきりします。
string grade = "B";
string message = grade switch
{
"A" => "優秀です",
"B" => "良いです",
"C" => "可です",
_ => "評価なし"
};
Console.WriteLine(message);
実用例:点数に応じた成績を出力する
- 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}");
ifとswitchの使い分け
比較ポイント | if 文 | switch 文 |
---|---|---|
柔軟な条件判定 | ◎(論理式も可能) | △(定数値が中心) |
可読性 | △(条件が多いと煩雑) | ◎(値で分岐する場合に明快) |
使い所 | 範囲・複雑な条件 | 値が明確なとき(曜日・コマンド等) |
繰り返し処理(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--;
}
do-while文:最低1回は必ず実行される
do-while
文は、処理を1回実行したあとに条件を判定する構文です。
int num = 0;
do {
Console.WriteLine("これは1回は実行されます");
}
while(num > 0);
foreach文:コレクションに対するループ
foreach
は、配列やリストなどのコレクションの全要素を順に処理するときに最適です。
- 基本構文
foreach (var 要素 in コレクション)
{
// 要素を使った処理
}
- 例)配列内のフルーツを表示
string[] fruits = { "りんご", "みかん", "バナナ" };
foreach(string fruit in fruits) {
Console.WriteLine(fruit);
}
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}");
ループ構文を使いこなそう
for
は カウンタ制御に便利while
は 条件ループに適しているdo-while
は 少なくとも1回実行したいときに使うforeach
は コレクション全体に対する処理にベスト
breakとcontinueの使いどころ
繰り返し処理(ループ)を行う中で、「途中でループを終了したい」あるいは「特定の条件だけ処理をスキップしたい」という場面は頻繁に登場します。
そんなときに使えるのが、break
と continue
です。
この章では、それぞれの構文の使い方と、具体的な活用例や注意点を解説します。
break
文:ループやswitchを途中で終了する
break
は、ループまたは switch
文をその時点で終了させます。
「これ以上処理を続ける必要がない」と判断したときに使います。
- 基本構文(for文の例)
for(int i = 0; i < 10; i++) {
if(i == 5) {
break;
}
Console.WriteLine(i);
}
0
1
2
3
4
- 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.
よく使われる例外クラスと発生条件
例外クラス名 | 主な発生条件 |
---|---|
DivideByZeroException | 0で除算したとき |
FormatException | 不正な書式の変換(文字列⇒数値など) |
NullReferenceException | null な変数のメンバーにアクセスしたとき |
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}");
}
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
を複数使い分ける finally
やthrow
も活用すれば、信頼性の高いエラーハンドリングができる
メソッドと配列の基礎
メソッドの定義と呼び出し方
メソッドとは?
メソッド(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);
}
値渡し(Pass by Value)と参照渡し(Pass by Reference)
- 値渡し(既定)
引数の値のコピーが渡され、元の変数には影響を与えません。
void Increment(int x)
{
x++;
}
int num = 10;
Increment(num);
Console.WriteLine(num); // → 出力:10(変更されない)
- 参照渡し(
ref
/out
)
元の変数を直接操作するには、ref
や out
を使います。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)の基本
- 特徴
- サイズ可変:要素の追加・削除が簡単
- 豊富なメソッドと柔軟性
System.Collections.Generic
のList<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
サンプル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
サンプル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
サンプル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));
メソッド × コレクションでコードの質を高める
- 配列・リストの操作は、メソッドと組み合わせることで読みやすく拡張性のあるコードに進化します。
- 実用的な処理は「分割・抽象化・再利用」を意識することが重要です。
- 条件抽出、集計、整形など、配列・リストを扱う共通処理はすべてメソッドで設計可能です。
クラスとオブジェクト指向プログラミングの基本
クラスとは何か?構造と使い方を理解しよう
クラスは「設計図」、オブジェクトは「実体」
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歳です。
}
}
クラスと構造体(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}");
}
}
実用例: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;
}
- バリデーション付きプロパティ
private int age;
public int Age
{
get => age;
set
{
if (value < 0)
throw new ArgumentException("年齢は0以上でなければなりません。");
age = value;
}
}
- 初期値付きプロパティ
public string Country { get; set; } = "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;
}
}
継承(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("ニャー");
}
}
ポリモーフィズム(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 | 依存性逆転原則 | 実装に依存せず、抽象に依存する |
OOPの柱を理解してクラス設計に活かす
- カプセル化:内部構造を隠し、安全な操作のみ公開
- 継承:共通機能を集約し、派生クラスで再利用・拡張
- ポリモーフィズム:型に依存せず多様な振る舞いを実行可能
- 抽象化と契約:柔軟で堅牢なシステムの土台を築く
C#で簡単なアプリケーションを作ってみよう
コンソールアプリケーションの開発手順
ここまでで、C#の基本文法やオブジェクト指向の考え方を学んできました。
この章では、実際に手を動かしてアプリケーションを作成することで、C#の実践的な使い方を体験していきましょう。
今回は「おみくじアプリ」を例に、プロジェクトの作成からコーディング、実行までの流れを解説します。
今回作るのは、コンソールで動く簡易おみくじアプリです。
おみくじアプリの仕様:
- 実行時に「Enterキーでおみくじを引く」と表示
- ユーザーがEnterを押すと、運勢(例:大吉〜凶)をランダム表示
Visual Studioでの手順:
- Visual Studioを起動
- 「新しいプロジェクトの作成」をクリック
- 「コンソール アプリ(.NET Core / .NET 6)」を選択
- プロジェクト名を入力(例:
OmikujiApp
) - 「作成」を押してプロジェクトを生成
Visual Studioで作成される初期テンプレートは以下のような構成です:
namespace OmikujiApp
{
class Program
{
static void Main(string[] args)
{
// アプリの処理をここに記述
}
}
}
コード例:
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("今日は慎重に行動しましょう。");
}
}
}
}
Visual Studioでコードを書き終えたら、次の方法で実行します:
- 「▶開始」ボタンをクリック
- または Ctrl + F5 を押してデバッグなしで実行
より実用的・面白いアプリにするためのアイデアも紹介します:
- 「もう一度引きますか?」の再試行ループを追加
- 「今日の日付」とともに運勢を表示(
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}歳ですね。");
安全な型変換: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 を活用し、例外を回避する |
入力の検証 | 空白・範囲・形式などのチェックを行う |
フィードバックの工夫 | ユーザーが理解しやすいメッセージを返す |
必要なら繰り返し処理 | while や do-while で再入力を促す |
条件分岐とループを使ったミニアプリの作成
数当てゲームを通じてロジックを身につけよう
これまで学んできた if
/ switch
などの条件分岐、for
/ while
などの繰り返し処理を組み合わせて、実践的なミニアプリケーションを作成してみましょう。
今回は、C#で「数当てゲーム」を開発し、ロジックの構築・エラーハンドリング・状態管理を体験します。
アプリの内容:数当てゲーム
- ランダムで選ばれた「1〜100の数字」をユーザーが当てる
- ユーザーが入力した数に対して「高すぎ」「低すぎ」などのヒントを表示
- 正解すると、試行回数と履歴を表示してゲーム終了
- Visual Studio を起動
- 「新しいプロジェクト」→「コンソール アプリ(.NET 6)」を選択
- プロジェクト名:
NumberGuessingGame
- 作成をクリック
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;
}
}
}
}
}
要素 | 解説 |
---|---|
Random.Next(1, 101) | 1〜100のランダムな整数を生成 |
while (true) | ユーザーが正解するまで無限ループ |
int.TryParse | 安全に文字列→整数へ変換 |
List<int> | 入力された数を履歴として記録 |
continue | 無効な入力をスキップし、次のループへ |
break | 正解時にループ終了 |
入力履歴の表示:
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;
}
if / else if / else
による条件分岐の設計while
ループによる継続的な入力処理TryParse
による型変換とエラーハンドリングList
によるデータの蓄積と出力break / continue
を使ったループ制御
ロジックを「作って動かす」ことで身につける
学習ポイント | 実践内容 |
---|---|
小さく作って確実に動かす | 最小限の構成で正常動作を確認 |
機能を追加しながら理解を深める | 履歴・バリデーション・再試行など段階的に拡張 |
トライ&エラーを恐れず試す | エラーを通じて理解が深まる構造体験型学習 |
実行結果の確認と改善ポイント
作ったあとが本番。完成から振り返りまでを実践しよう
前節で完成した「数当てゲーム」を例に、動作確認の手順と、ユーザー体験(UX)を高めるための改善策について解説します。
アプリを作り終えたあとは、単なる動作確認にとどまらず、コードの見直し・操作性の向上・エラー耐性の強化など、多角的な視点で振り返ることが重要です。
実行結果を確認する方法
- Visual Studioで実行
- 画面上部の ▶(開始)ボタンをクリック
- または
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#ライフが、楽しく、そして実り多きものになることを願っています。
引き続き、学習を応援しています! 💻✨
コメント