前回はLINQの基本について学びました。
今回は、C#における「オブジェクト指向」と「クラス」の基本について学びます。
最初は少しとっつきにくい内容かもしれませんが、その仕組みを理解すると、データや処理を整理して扱えるようになり、実務でも非常に役立ちます。
初心者の方でも「クラス設計の基本」が理解できるよう、丁寧に解説していきます。
オブジェクト指向とクラスの概念
「オブジェクト指向」とは、現実世界の「モノ(=オブジェクト)」をプログラムの中でも同じように扱おうという考え方です。
例えばブログの記事には、タイトル・著者・本文など様々な情報がありますが、これらをバラバラの変数で管理するのは複雑になりがちです。
そこで「記事」という1つのまとまり(オブジェクト)として扱えるようにするのがオブジェクト指向です。
その「記事」を作るための設計図が「クラス」になります。
設計図である「クラス」から「オブジェクト(インスタンスともいう)」を生成することで、実際のデータとして利用できるようになります。
以下の図は、クラスとオブジェクトの関係を簡潔に表したものです。

クラスの定義とオブジェクトの作成
クラスはclass
というキーワードを使い、次のような構文で定義します。
アクセス修飾子 class クラス名
{
クラスの中身
}
アクセス修飾子とは、「どこからこのクラスを使えるか」を決めるキーワードです。例えば public
を指定すると、他の場所からもこのクラスを自由に使えるようになります。
アクセス修飾子には他に private
や internal
などがあります。
これらについては、記事の後半で改めて詳しく解説します。
以下は、タイトルと著者の情報を持つArticle
クラスの例です。
public class Article
{
public string Title { get; set; }
public string Author { get; set; }
}
このようにクラスを定義することで、共通の構造を持ったデータ(オブジェクト)を生成できるようになります。
クラスからオブジェクトを作るにはnew
キーワードを使います。
// Articleクラスからオブジェクトを生成
var article = new Article();
// オブジェクトのタイトルと著者プロパティに値を設定
article.Title = "C#入門";
article.Author = "山田太郎";
このように、「設計図」であるArticle
クラスからオブジェクトのarticle
を生成し、1件の記事データとして扱うことができます。
プロパティとオブジェクト初期化子
先ほどの Article
クラスでは、Title
と Author
を「プロパティ」として定義しました。
プロパティは、クラスのデータ(値)に対して外部からの読み取りや書き込みを行うための仕組みです。
プロパティの定義
C#では、次のようにプロパティを定義します。
public string Title { get; set; }
get
は値を取得する処理(getter)、set
は値を設定する処理(setter)を表しています。
以下のようにして、プロパティの値を設定・取得できます。
article.Title = "C#入門"; // 値を設定する(setterが呼ばれる)
Console.WriteLine(article.Title); // 値を取得する(getterが呼ばれる)
必要に応じて、get
のみを定義して読み取り専用にしたり、set
にアクセス制限を加えることで、柔軟なアクセス制御が可能になります。
オブジェクト初期化子とは?
プロパティとあわせてよく使われるのが、オブジェクト初期化子です。
オブジェクト初期化子を使うと、オブジェクト生成と同時にプロパティへ値を設定できます。
var article = new Article
{
Title = "C#入門",
Author = "山田太郎"
};
プロパティが複数ある場合でも、まとめて初期化できるため、コードの見通しが良くなるというメリットがあります。
メソッド
クラスにはデータだけでなく、データに関連する処理(振る舞い)も定義できます。
この処理のまとまりを「メソッド」と呼びます。
メソッドの定義
C#では、次のようなルールにしたがってメソッドを定義します。
アクセス修飾子 戻り値の型 メソッド名(引数)
{
実行したい処理
}
それぞれの意味は次の通りです。
- アクセス修飾子:どこからこのメソッドを使えるかを指定する
- 戻り値の型:メソッドの処理結果として返す値のデータ型(
void
は何も返さないことを意味する) - メソッド名:先頭を大文字で命名する(パスカルケース・アッパーキャメルケース)
- 引数:外部からメソッドに渡す値。() の中に指定する(無い場合は空欄)
例えば、記事のタイトルと著者を表示するメソッドは次のように定義できます。
public void Print()
{
Console.WriteLine($"{Title} by {Author}");
}
このメソッドは void
かつ ()
の中が空であることから、戻り値も引数も無いことがわかります。
メソッドは次のように呼び出すことができます。
var article = new Article
{
Title = "C#入門",
Author = "山田太郎"
};
article.Print(); // 出力: C#入門 by 山田太郎
このように、クラスから生成したオブジェクトに対して、.
(ドット)を使ってメソッドを呼び出すのがC#の基本的な書き方です。
戻り値とは?
戻り値とは、メソッドの処理結果として呼び出し元に返される値のことです。
C#では、メソッドの定義時に戻り値の型を指定し、return
文で値を返します。
例えば、タイトルの文字数を返すメソッドは次のように書けます。
public int GetTitleLength()
{
return Title.Length;
}
このメソッドは int
(整数)型の戻り値を持っており、呼び出し側でその値を受け取って利用できます。
var length = article.GetTitleLength();
Console.WriteLine(length); // 出力: 5
このように、戻り値を使うとメソッドの処理結果を他の処理につなげることができるようになります。
引数とは?
引数とは、メソッドに外部から渡す値のことです。
メソッド内の処理に必要な情報を、()
の中に「型+名前」で定義します。
例えば、記事のタイトルを外部から受け取って変更するメソッドは以下のように定義します。
public void SetTitle(string newTitle)
{
Title = newTitle;
}
この string newTitle
が引数です。呼び出し側で渡された文字列が newTitle
に入り、メソッド内で Title
に設定されます。
article.SetTitle("最新のC#ガイド");
引数を使えば、処理の内容を呼び出しごとに柔軟に変えることができるようになります。
Articleクラスの全体像
最後に、先ほど紹介した3つのメソッドを Article
クラスの中にすべて定義した例を紹介します。
public class Article
{
// プロパティ(データ)
public string Title { get; set; }
public string Author { get; set; }
// タイトルと著者を表示するメソッド
public void Print()
{
Console.WriteLine($"{Title} by {Author}");
}
// タイトルの文字数を返すメソッド
public int GetTitleLength(戻り値あり)
{
return Title.Length;
}
// タイトルを変更するメソッド(引数あり)
public void SetTitle(string newTitle)
{
Title = newTitle;
}
}
このように、「データ(プロパティ)」と「処理・振る舞い(メソッド)」を1つのクラスにまとめることで、コードの構造が明確になり、保守しやすくなります。
コンストラクタでの初期化
クラスからオブジェクトを生成する際に、最初から特定の値を設定したいことがあります。
そのために使うのが「コンストラクタ」です。
コンストラクタは、クラス名と同じ名前を持つ特別なメソッドで、オブジェクトが生成されるときに自動で呼び出されます。
以下は、タイトルと著者を指定して Article
を初期化するコンストラクタの例です。
public class Article
{
public string Title { get; set; }
public string Author { get; set; }
public Article(string title, string author)
{
Title = title;
Author = author;
}
}
呼び出すときは、new
の後に引数を渡すことで、すぐに初期化されたオブジェクトが得られます。
var article = new Article("C#入門", "山田太郎");
このように、コンストラクタを使うと「この値は必ず設定してほしい」というルールを明確にできます。
特に、必須項目を確実に受け取りたいときによく使われます。
一方、値を柔軟に設定したい場合には、先ほど紹介したオブジェクト初期化子が便利です。
var article = new Article
{
Title = "C#入門",
Author = "山田太郎"
};
この書き方では、まず引数なしのコンストラクタが呼ばれ、続けてプロパティに値が代入されます。
基本的には「必ず設定したい値がある場合はコンストラクタ」・「柔軟に設定したい場合はオブジェクト初期化子」のように使い分けましょう。
C# 11以降では、プロパティに required
修飾子を付けることで、オブジェクト初期化子による初期値設定を必須にすることができるようになりました。
シンプルな初期化であれば、required とオブジェクト初期化子を組み合わせた方が柔軟に書ける場面もあります。
アクセス修飾子の基本
これまでのクラスやプロパティ、メソッドの定義でたびたび登場してきたように、C#ではアクセス修飾子を使って、どこからそのメンバーにアクセスできるかを制御することができます。
最も基本的なアクセス修飾子は以下の3つです。
public
:どこからでもアクセス可能(外部に公開)private
:そのクラスの内部からのみアクセス可能(外部には非公開)internal
:同じアセンブリ(プロジェクト)内からはアクセス可能だが、外部のプロジェクトからは不可
たとえば、以下のようにアクセス修飾子を使って Title
を外部に公開しつつ、id
はクラス内部だけで管理することができます。
public class Article
{
public string Title { get; set; }
private int id;
}
このようにアクセス修飾子を適切に使うことで、クラスの内部構造を隠して安全に保つことができます。
この考え方は「カプセル化」と呼ばれ、オブジェクト指向の重要な要素のひとつです。
まとめ
クラスを使うことで、関連するデータと処理をひとまとまりとして表現できます。
これは、実務のWebアプリ開発において「データモデル」や「ビジネスロジック」を設計するときに不可欠な考え方です。
次回は、さらに一歩進んで「継承」や「インターフェース」など、クラスを発展的に活用する方法を学んでいきます。