「プログラム入門」の資料でC#の基本的な書き方を学んだ皆さん、お疲れ様でした! ここからは、より複雑な処理を効率的に記述し、大規模なアプリケーションを開発するために不可欠なC#の応用概念を学んでいきましょう。
メソッド(Method)は、特定の処理のまとまりに名前を付けて定義するものです。これにより、同じ処理をプログラムのあちこちで何度も書く必要がなくなり、コードの重複を防ぎ、読みやすく、管理しやすくなります。
メソッドは、**戻り値の型、メソッド名、引数**から構成されます。
using System;
// メソッドを定義するクラス
public class Program
{
// プログラムのエントリーポイント(開始地点)
public static void Main(string[] args)
{
// メソッドの呼び出し例
Greet("太郎"); // 引数 "太郎" を渡してGreetメソッドを呼び出す
int result = Add(10, 5); // Addメソッドを呼び出し、戻り値をresultに格納
Console.WriteLine($"10 + 5 = {result}"); // 結果を表示
}
// 戻り値なし、引数ありのメソッド
public static void Greet(string name)
{
Console.WriteLine($"こんにちは、{name}さん!");
}
// 戻り値あり、引数ありのメソッド
public static int Add(int num1, int num2)
{
int sum = num1 + num2;
return sum; // 計算結果を返す
}
}
public static
: 現時点では「おまじない」と考えてください(後に「アクセス修飾子」と「静的メソッド」として詳しく学びます)。void
: メソッドが何も値を返さない場合に指定します。int
(戻り値の型): メソッドが整数値を返すことを示します。Greet
, Add
: メソッドの名前です。(string name)
, (int num1, int num2)
: **引数(ひきすう)**です。メソッドに渡すデータ(入力)を指定します。return sum;
: メソッドの処理結果として値を返すときに使います。$""
): C# 6.0から導入された便利な機能で、文字列内に直接変数の値を埋め込むことができます。C#はオブジェクト指向プログラミング(OOP)言語です。OOPは、現実世界を「もの(オブジェクト)」と「もの同士の関係」で捉え、それをプログラムで表現する考え方です。これにより、複雑なシステムをより分かりやすく、管理しやすく開発できます。
クラスは、「ものの設計図」のようなものです。例えば、「車」というクラスを定義するなら、その車がどんな「特徴(色、メーカー、速度など)」を持ち、どんな「動作(走る、止まる、曲がるなど)」ができるのかを設計します。
オブジェクトは、クラスという設計図に基づいて実際に作られた「もの」そのものです。例えば、「車」の設計図から「赤色のトヨタの車」や「青色のホンダの車」といった具体的な車を複数作ることができます。それぞれの具体的な車がオブジェクトです。
using System;
// 人を表すクラスを定義
public class Person
{
// フィールド(特徴、プロパティとも言う)
public string Name;
public int Age;
// メソッド(動作)
public void SayHello()
{
Console.WriteLine($"こんにちは、私の名前は{Name}です。");
}
public void CelebrateBirthday()
{
Age++; // 年齢を1増やす
Console.WriteLine($"{Name}は{Age}歳になりました!");
}
}
public class Program
{
public static void Main(string[] args)
{
// Personクラスのオブジェクト(インスタンス)を作成
Person person1 = new Person();
person1.Name = "アリス"; // オブジェクトのNameを設定
person1.Age = 30; // オブジェクトのAgeを設定
person1.SayHello(); // オブジェクトのメソッドを呼び出す
person1.CelebrateBirthday(); // オブジェクトのメソッドを呼び出す
Console.WriteLine("---");
// 別のPersonオブジェクトを作成
Person person2 = new Person();
person2.Name = "ボブ";
person2.Age = 22;
person2.SayHello();
}
}
public class Person
: Person
という名前のクラスを定義しています。public string Name;
: オブジェクトが持つ特徴(データ)を定義する「フィールド」です。public void SayHello()
: オブジェクトができる動作(処理)を定義する「メソッド」です。Person person1 = new Person();
: new Person()
を使って、Person
クラスから新しいオブジェクト(インスタンス)を作成し、person1
という変数に格納しています。person1.Name = "アリス";
: .
(ドット)を使って、オブジェクトのフィールドやメソッドにアクセスします。コンストラクター: オブジェクトを作成する際に初期設定を行う特別なメソッドです。例えば、public Person(string name, int age) { Name = name; Age = age; }
のように定義し、Person person3 = new Person("チャーリー", 40);
のように使えます。
これまでは一つの変数に一つのデータしか格納できませんでした。しかし、複数の同じ種類のデータをまとめて扱いたい場合が多くあります。そのために配列やリストを使います。
配列は、同じデータ型の複数のデータをまとめて格納できる「固定長」のデータ構造です。一度配列のサイズを決めると、後から変更することはできません。
using System;
public class Program
{
public static void Main(string[] args)
{
// 整数型(int)の配列を宣言し、初期化
int[] numbers = new int[5]; // サイズが5のint型配列を作成
// 配列に値を代入
numbers[0] = 10; // 0番目の要素に10を代入
numbers[1] = 20;
numbers[2] = 30;
numbers[3] = 40;
numbers[4] = 50; // 4番目の要素(最後の要素)
// 配列の要素にアクセスして表示
Console.WriteLine($"numbers[0] の値: {numbers[0]}"); // 10
Console.WriteLine($"numbers[2] の値: {numbers[2]}"); // 30
// 配列の全ての要素をループで表示
Console.WriteLine("--- 配列の全要素 ---");
for (int i = 0; i < numbers.Length; i++)
{
Console.WriteLine($"numbers[{i}] = {numbers[i]}");
}
// 初期化と同時に値を設定することも可能
string[] names = { "Alice", "Bob", "Charlie" };
Console.WriteLine($"names[1] の値: {names[1]}"); // Bob
}
}
int[] numbers = new int[5];
: int
型の要素を5つ持てる配列を宣言しています。インデックスは0から始まります(0, 1, 2, 3, 4)。numbers[0]
: 配列の最初の要素にアクセスします。numbers.Length
: 配列の要素数(サイズ)を取得できます。リストは、配列と同じように複数のデータを格納できますが、こちらは「可変長」のデータ構造です。要素の追加や削除が容易で、サイズを後から変更できます。配列よりも柔軟なため、多くの場面でリストが使われます。
using System;
using System.Collections.Generic; // Listを使うために必要
public class Program
{
public static void Main(string[] args)
{
// string型のリストを宣言し、初期化
List<string> fruits = new List<string>();
// リストに要素を追加
fruits.Add("Apple");
fruits.Add("Banana");
fruits.Add("Orange");
// リストの要素にアクセスして表示
Console.WriteLine($"最初のフルーツ: {fruits[0]}"); // Apple
// リストの要素をループで表示
Console.WriteLine("--- リストの全要素 ---");
foreach (string fruit in fruits) // foreachループもよく使われます
{
Console.WriteLine(fruit);
}
// 要素を削除
fruits.Remove("Banana"); // "Banana"という値を削除
// fruits.RemoveAt(0); // 0番目の要素を削除 (Appleが削除される)
Console.WriteLine("--- Banana削除後のリスト ---");
foreach (string fruit in fruits)
{
Console.WriteLine(fruit);
}
Console.WriteLine($"リストの現在の要素数: {fruits.Count}"); // 要素数を取得
}
}
using System.Collections.Generic;
: リストを使うために必要な宣言です。List<string> fruits = new List<string>();
: string
型の要素を格納するリストを宣言しています。<>
(ジェネリック)で格納するデータの型を指定します。fruits.Add("Apple");
: リストの末尾に要素を追加します。fruits.Remove("Banana");
: 指定した値をリストから削除します。fruits.Count
: リストの現在の要素数を取得できます。foreach
ループ: 配列やリストなどのコレクションの全要素を順番に処理するのに非常に便利です。プログラムが実行中に予期せぬ問題(例: ファイルが見つからない、数値を0で割ろうとした、無効な形式の入力を受け取ったなど)に遭遇することを例外(Exception)と呼びます。例外が発生すると、通常、プログラムは停止してしまいます。
例外処理(Exception Handling)は、このような予期せぬエラーが発生した場合でも、プログラムが安全に動作を続けられるようにするための仕組みです。
try-catch
ステートメントC#では、try-catch
ブロックを使って例外処理を記述します。
try
ブロック: 例外が発生する可能性があるコードを記述します。catch
ブロック: try
ブロック内で例外が発生した場合に、その例外を「捕まえ」、エラーに対する処理を記述します。using System;
public class Program
{
public static void Main(string[] args)
{
Console.Write("数値を入力してください: ");
string input = Console.ReadLine();
try
{
// ここで例外が発生する可能性がある
int number = int.Parse(input); // 文字列を数値に変換(変換できない場合は例外)
int result = 100 / number; // 0で割ると例外が発生する
Console.WriteLine($"計算結果: {result}");
}
catch (FormatException ex) // 文字列が数値に変換できない例外を捕まえる
{
Console.WriteLine("エラー: 無効な形式の数値が入力されました。");
Console.WriteLine($"詳細: {ex.Message}"); // エラーメッセージを表示
}
catch (DivideByZeroException ex) // 0で除算した例外を捕まえる
{
Console.WriteLine("エラー: 0で割ることはできません。");
Console.WriteLine($"詳細: {ex.Message}");
}
catch (Exception ex) // その他の全ての例外を捕まえる(汎用的な例外ハンドリング)
{
Console.WriteLine("予期せぬエラーが発生しました。");
Console.WriteLine($"詳細: {ex.Message}");
}
finally
{
// 例外の有無にかかわらず、必ず実行される処理(リソースの解放など)
Console.WriteLine("処理が終了しました。");
}
Console.WriteLine("--- プログラムは継続して実行されます ---");
}
}
try { ... }
: 正常に実行されるべきコードを記述します。catch (例外の型 変数名) { ... }
: try
ブロック内で特定の種類の例外が発生した場合に実行されます。FormatException
やDivideByZeroException
のように、より具体的な例外型を指定することで、エラーの種類に応じて異なる処理ができます。Exception ex
: 全ての例外の基底クラスであり、どんな例外でも捕まえることができます。通常は、具体的な例外をキャッチした後に、それ以外の全ての例外をキャッチするために最後に記述します。ex.Message
: 発生した例外に関する詳細なメッセージを取得できます。finally { ... }
: try
ブロックの処理が完了した後、例外が発生したかどうかに関わらず、必ず実行されるコードを記述します。ファイルのクローズなど、リソースの解放によく使われます。注意: 例外処理は万能薬ではありません。できる限りエラーが発生しないように、入力値の検証(バリデーション)など事前に対策を講じることが重要です。
この資料で、C#のメソッド、クラスとオブジェクト、配列とリスト、そして例外処理といった重要な概念を学びました。これらを理解し使いこなすことで、より堅牢で、保守しやすく、拡張性の高いプログラムを開発できるようになります。
次のステップとして、これらの概念を組み合わせて、小さなアプリケーションを作成してみましょう。 例えば、以下のようなものが考えられます。
実際に手を動かし、様々な問題を解決していく中で、これらの概念への理解がさらに深まります。頑張ってください!