C#: クラスとオブジェクト

1. クラスが必要な理由

C#は、ほぼすべてがオブジェクトであるオブジェクト指向言語です。これまではトップレベル文を使ってコードを書いてきましたが、実際のC#プログラムはクラスから構成されています。クラスはオブジェクトの設計図であり、データ(フィールド)と動作(メソッド)を定義します。一方、オブジェクトはクラスの具体的なインスタンスです。


2. クラスの定義

クラスを定義するには、キーワードclassを使用してください。クラス名はパスカルケース(各単語の頭文字を大文字にする)で記述してください。

CSHARP
class Person
{
    public string Name;
    public int Age;

    public void SayHello()
    {
        System.Console.WriteLine($"Hello, I'm {Name}, {Age} years old.");
    }
}

3. オブジェクトの作成

newというキーワードを使用して、クラスからオブジェクトを作成します:

CSHARP
Person p = new Person();
p.Name = "Tom";
p.Age = 18;
p.SayHello();
TEXT 📖 参照専用
Hello, I'm Tom, 18 years old.

newは、独自のフィールドのコピーを持つ独立したオブジェクトを作成します。


4. フィールドとフィールドの初期化

変数には、宣言時に初期値を割り当てることができます:

CSHARP
class Student
{
    public string Name = "Unknown";
    public int Score = 0;
}

初期値が指定されていない場合、数値型はデフォルトで0となり、参照型はデフォルトでnullとなります。

アクセス修飾子はフィールドの可視性を制御します:

修飾語 意味
public どこからでもアクセス可能
private クラス内でのみアクセス可能(デフォルト)

通常、フィールドはprivateに設定され、メソッドやプロパティを通じてアクセスが制御されます。

▶ サンプル

CSHARP
using System;

class BankAccount
{
    private decimal balance = 1000m;

    public void Deposit(decimal amount)
    {
        balance += amount;
        Console.WriteLine($"Deposited {amount}, balance is {balance}");
    }

    public void ShowBalance()
    {
        Console.WriteLine($"Current balance: {balance}");
    }
}

class Program
{
    static void Main()
    {
        BankAccount acc = new BankAccount();
        acc.ShowBalance();
        acc.Deposit(500m);
    }
}
▶ 試してみよう
TEXT 📖 参照専用
Current balance: 1000
Deposited 500, balance is 1500

5. 方法

メソッドとは、クラス内で定義され、オブジェクトの挙動を表す関数のことです。メソッドは、同じクラス内のフィールドにアクセスすることができます:

CSHARP
class Calculator
{
    private int result = 0;

    public void Add(int value)
    {
        result += value;
    }

    public int GetResult()
    {
        return result;
    }
}

6. this キーワード

thisは、現在のオブジェクトインスタンスを指します。最も一般的な用途は、同じ名前を持つフィールドとパラメータを区別することです:

CSHARP
class Person
{
    public string Name;
    public int Age;

    public Person(string Name, int Age)
    {
        this.Name = Name;
        this.Age = Age;
    }
}

7. コンストラクタ

コンストラクタは、オブジェクトが作成される際に自動的に呼び出され、オブジェクトの初期化に使用されます。

(1) パラメータなしのコンストラクタ

コンストラクタが定義されていない場合、コンパイラは自動的に引数なしのコンストラクタを生成します:

CSHARP
class Dog
{
    public string Name;

    public Dog()
    {
        Name = "Unnamed";
    }
}

(2) パラメータ付きコンストラクタ

CSHARP
class Dog
{
    public string Name;

    public Dog(string name)
    {
        Name = name;
    }
}

⚠️ コンストラクタを定義すると、コンパイラはそれ以降、パラメータなしのコンストラクタを自動的に生成しなくなります。

(3) コンストラクタのオーバーロード

異なるパラメータを持つ複数のコンストラクタを定義することができます:

CSHARP
class Dog
{
    public string Name;
    public int Age;

    public Dog()
    {
        Name = "Unnamed";
        Age = 0;
    }

    public Dog(string name)
    {
        Name = name;
        Age = 0;
    }

    public Dog(string name, int age)
    {
        Name = name;
        Age = age;
    }
}

(4) コンストラクタの連鎖

this(...)を使用すると、あるコンストラクタから別のコンストラクタを呼び出すことができ、コードの重複を回避できます:

CSHARP
class Dog
{
    public string Name;
    public int Age;

    public Dog() : this("Unnamed", 0) { }

    public Dog(string name) : this(name, 0) { }

    public Dog(string name, int age)
    {
        Name = name;
        Age = age;
    }
}

▶ サンプル

CSHARP
using System;

class Book
{
    public string Title;
    public string Author;
    public decimal Price;

    public Book() : this("Unknown", "Unknown", 0m) { }

    public Book(string title, string author) : this(title, author, 29.9m) { }

    public Book(string title, string author, decimal price)
    {
        Title = title;
        Author = author;
        Price = price;
    }

    public void PrintInfo()
    {
        Console.WriteLine($"\"{Title}\" Author: {Author} Price: {Price}");
    }
}

class Program
{
    static void Main()
    {
        Book b1 = new Book();
        Book b2 = new Book("C# Basics", "Alice");
        Book b3 = new Book("Advanced C#", "Bob", 59.9m);

        b1.PrintInfo();
        b2.PrintInfo();
        b3.PrintInfo();
    }
}
▶ 試してみよう
TEXT 📖 参照専用
"Unknown" Author: Unknown Price: 0
"C# Basics" Author: Alice Price: 29.9
"Advanced C#" Author: Bob Price: 59.9

8. デストラクタ

オブジェクトがガベージコレクションされる前に、デストラクタが呼び出されます。構文は~ClassName()です:

CSHARP
class Resource
{
    ~Resource()
    {
        Console.WriteLine("Object is being reclaimed");
    }
}

📌 C# には自動ガベージコレクション(GC)が備わっているため、デストラクタを手動で記述する必要はほとんどありません。デストラクタは、アンマネージドリソース(ファイルハンドルやデータベース接続など)を解放するためにのみ使用されます。これについては、後のレッスンで詳しく説明します。


9. オブジェクト初期化子

C# 3.0 では、オブジェクト初期化子の構文が導入されました。これにより、newを使用する際、パブリックフィールドやプロパティに値を直接代入できるようになりました:

CSHARP
Person p = new Person { Name = "Lily", Age = 20 };

これは、次の式と同等です:

CSHARP
Person p = new Person();
p.Name = "Lily";
p.Age = 20;

オブジェクト初期化子は、パラメータ付きコンストラクタと組み合わせることができます:

CSHARP
Person p = new Person("Lily") { Age = 20 };

▶ サンプル

CSHARP
using System;

class Rectangle
{
    public double Width = 1;
    public double Height = 1;

    public double Area()
    {
        return Width * Height;
    }
}

class Program
{
    static void Main()
    {
        Rectangle r1 = new Rectangle();
        Rectangle r2 = new Rectangle { Width = 5, Height = 3 };
        Rectangle r3 = new Rectangle { Width = 10 };

        Console.WriteLine($"r1 area: {r1.Area()}");
        Console.WriteLine($"r2 area: {r2.Area()}");
        Console.WriteLine($"r3 area: {r3.Area()}");
    }
}
▶ 試してみよう
TEXT 📖 参照専用
r1 area: 1
r2 area: 15
r3 area: 10

10. new と null の違い

概念 意味
new ClassName() ヒープ上にオブジェクトを作成し、そのオブジェクトへの参照を返す
null いかなるオブジェクトも指しておらず、参照型のデフォルト値である
CSHARP
Person p1 = new Person();
Person p2 = null;

Console.WriteLine(p1 == null);
Console.WriteLine(p2 == null);
TEXT 📖 参照専用
False
True

⚠️ nullリファレンス上のメンバーにアクセスすると、NullReferenceExceptionが発生します。これはC#で最も一般的な実行時エラーです:

CSHARP
Person p = null;
p.SayHello();

💡 アクセスする前に、nullが含まれているか確認してください:

CSHARP
if (p != null)
{
    p.SayHello();
}

❓ よくある質問

Q コンストラクタを記述しなかった場合はどうなりますか?
A コンパイラが、フィールドにデフォルト値を代入するパラメータなしのコンストラクタを自動的に生成します。
Q パラメータ付きコンストラクタを定義した後でも、パラメータなしのオブジェクトを作成することはできますか?
A いいえ、パラメータなしのコンストラクタも手動で定義しない限り、できません。
Q これは静的メソッドでも使用できますか?
A いいえ、これは現在のインスタンスを指すものであり、静的メソッドはインスタンスに関連付けられていないためです。
Q オブジェクト初期化子でプライベートフィールドに値を代入することはできますか?
A いいえ、初期化できるのはアクセス可能なメンバー(パブリックフィールドまたはプロパティ)のみです。
Q null と 0 は同じものですか?
A いいえ。null は「参照がない」ことを意味しますが、0 は数値型の値です。値型は null になることはありません。

📖 まとめ

📝 練習問題

  1. Carクラスを定義し、その中にBrand(文字列)およびSpeed(整数)のフィールド、Speedの値を増加させるAccelerate(int amount)メソッド、およびSpeedを0に初期化する引数なしのコンストラクタを定義する
  2. Carクラスにパラメータ付きコンストラクタCar(string brand)を追加し、this(...)を使用してコンストラクタチェーンを実装する
  3. オブジェクト初期化子を使用してCarオブジェクトを作成し、BrandとSpeedを設定した後、Accelerateメソッドを呼び出し、最終的なSpeedを出力する
  4. 以下の内容を実装するコードを記述してください:Carの参照をnullに代入し、そのメンバにアクセスしようとし、try-catch を使ってNullReferenceExceptionを捕捉し、メッセージを出力する
Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%