注目キーワード
  1. プログラミング
  2. C#

【C#】ジェネリッククラスを使用する方法

C#

はじめに

こうちゃ
こんにちは、こうちゃです。
以前、以下の記事でジェネリックメソッドの使い方を説明しました。
その際に、「ジェネリッククラスというものもありますよ〜」とさらっと記載しました。
関連記事

はじめに こうちゃ こんにちは、こうちゃです。 今回は、C#でジェネリックメソッド(テンプレート関数)を使用する方法 について説明していきます。 ジェネリックメソッドの使用方法  ジ[…]

今回は、C#でジェネリッククラスを使用する方法 について説明していきます。
  • ジェネリッククラスの作成・使用方法
  •  ジェネリッククラスを使用したい方
  • 同じ内容の処理なのに、型が違うために同じクラスを何個も作らないといけないと悩んでいる方
こうちゃ
それでは、やっていきましょう!

ジェネリッククラスとは

以前、ジェネリックメソッドについては説明しましたね。
ジェネリッククラスは、ジェネリックメソッドのクラスバージョンです。
つまり、型が違うだけで処理内容自体は同じというクラスを実現するための仕組み になります。
共通処理を実装したクラスを作成しておき、インスタンス化する際に型を指定できる というイメージですね。
以下に例として、四則演算を行うクラスをジェネリッククラス使用なしで作ってみましょう。

ジェネリッククラスを使用しない場合

class IntCalcurator
{
    public int Add(int a, int b)
    {
        return a + b;
    }

    public int Subtract(int a, int b)
    {
        return a - b;
    }

    public int Multiply(int a, int b)
    {
        return a * b;
    }

    public int Divide(int a, int b)
    {
        if (b == 0)
            throw new DivideByZeroException("Cannot divide by zero.");

        return a / b;
    }
}
class FloatCalculator
{
    public float Add(float a, float b)
    {
        return a + b;
    }

    public float Subtract(float a, float b)
    {
        return a - b;
    }

    public float Multiply(float a, float b)
    {
        return a * b;
    }

    public float Divide(float a, float b)
    {
        if (b == 0)
        {
            throw new DivideByZeroException("Cannot divide by zero.");
        }
        return a / b;
    }
}

このように、ジェネリッククラスを使用しない場合は、「IntCalculator」「FloatCalculator」のように同じ処理内容のクラスを必要な数分作らないといけなくなります。

もし、「Add」メソッドの内容を変更する必要が出てきたときに「IntCalculator」「FloatCalculator」の2クラスを修正しないといけないので大変ですね。

これを対応するために、ジェネリッククラスを使用していきます。

ジェネリッククラスの作り方

基本構文

class クラス名<型引数"Type">
{
    // 型引数"Type" を使った処理
}

ジェネリックメソッドと形は似ていますね。
「型引数”Type”」に任意の型を指定できるので、クラス内部の処理を”Type”を使用して作成すれば共通化できます。

型制約 (where句)

ジェネリックメソッドで「型制約」というものがあったのを覚えているでしょうか?
「型引数”Type”」がどのような型かわからないから、演算など特定の処理はできないという問題を解決するためのものでした。

ジェネリックメソッドの「型制約」と考え方は変わりません。
例えば今回の四則演算クラスでは、「型引数”Type”」は 演算可能な型 ということが確定しています。

なので、「Calculator」クラスを作成するとしたら以下のようになるでしょう。

class Calculator<Type>
    where Type : INumber<Type>
{

}

四則演算クラス「Calculater」のコード例

class Calculator<Type>
    where Type : INumber<Type>
{
    public Type Add(Type a, Type b)
    {
        return a + b;
    }

    public Type Subtract(Type a, Type b)
    {
        return a - b;
    }

    public Type Multiply(Type a, Type b)
    {
        return a * b;
    }

    public Type Divide(Type a, Type b)
    {
        if (b == Type.Zero)
        {
            throw new DivideByZeroException();
        }
        return a / b;
    }
}

このようにクラスを作成することで、「Type」に「int」や「float」を指定して四則演算を行うことができます。
型制約で「INumber」を指定することで、「Type」型の演算が可能になっていますね。
これでジェネリッククラスは完成です。

ジェネリッククラスの使い方

では実際にジェネリッククラス「Calculator」を使用していきましょう。

var intCalc = new Calculator<int>();          // Calculator<int> 型のインスタンス
Console.WriteLine(intCalc.Add(10, 5));        // 15

var floatCalc = new Calculator<float>();      // Calculator<float> 型のインスタンス
Console.WriteLine(floatCalc.Divide(10f, 2f)); // 5

型を指定してインスタンス化することで、「Calculator」クラスの「Type」に指定した型が適用されます。

まとめ

ジェネリッククラスは、インスタンス化時に型を決定させることのできるクラス でした。

一番のメリットとしては 同じ処理を複数の型で使いまわせる ことでしょう。
ジェネリッククラスにせず同じ処理のクラスを何個も作ると、修正する時大変です。
ジェネリッククラスを使用することで、修正は1クラスのみで済むので、かなり便利になりますね。

ジェネリッククラスは、処理自体は同じだけど複数の型で動作する可能性がある という場合に最適です。

さいごに

今回はジェネリッククラスについて説明しました。

以前に解説したジェネリックメソッドと似ていましたね。
そんなにものすごい多用する機能ではありませんが、ジェネリッククラスで作成しておくとプロジェクトを超えて再利用できるという場合があるので非常に便利です!

ぜひ使ってみてくださいね。
今回はここまで♪

こうちゃ
それではみなさま、お疲れ様でした!
楽しいプログラミングライフを!
最新情報をチェックしよう!