C#のList<T>とインターフェイス

C# コンピュータ
C#

インターフェイスを使ったことはあっても自分で作る機会ほどんどないのですが、たまたま使わざるをえない状況になりましたので、サンプルプログラムを書いてみたいと思います。

using System.Collections.Generic;

namespace aaaa;

interface ISample
{
    public void Say();
}
class Sample : ISample
{
    public void Say()
    {
        Console.WriteLine("Hi!!");
    }
}
class Dog : ISample
{
    public void Say()
    {
        Console.WriteLine("Bow");
    }
    public void Run()
    {
        Console.WriteLine("Very Fast");
    }
}
class Program
{
    static void Main()
    {
        // 異なるオブジェクト(Sample(), Dog())を一つのコンテナ(samples)に混載する。
        List<ISample> samples = [new Sample(), new Dog()];

        foreach(var x in samples)
        {
            // ISampleで定義しているSay()は普通に呼び出せる。
            x.Say();
            // Run()はDogのみなのでDogへキャスト
            Dog? dog = x as Dog;
            // キャストできた場合Run()を実行
            dog?.Run();
        }
    }
}

SampleとDogは異なるクラスのインスタンスですが、ISampleを継承しているのでList<ISample> にセットすることが出来ました。
List<ISample>要素はISampleですのでforeachでは、ISampleで定義されているSay()メソッドは実行できますが、ISampleでは定義されていないDogのRun()は実行することが出来ません。サンプルプログラムではasでDogにキャストして成功した場合(Nullでない場合)Run()メソッドを実行しています。キャストは安全確実かは自信がないですが、とりあえず実行は出来るようです。

インターフェイスは直接オブジェクトを生成することが出来ないので、クラスを定義を強制するために使われる仕組みで、プログラムの処理的な部分に使うことが無いイメージがありました。ライブラリの関数やメソッドの説明で戻り値にIEnumerable インターフェイスが指定されていることを目にしたこともありましたが、これはIEnumerable インターフェイスから派生したクラスのオブジェクトで受け取るものと思い込んでいました。

とは言え具体的な使い道があるかといいますと、思いつかないところみると、普段からオブジェクト指向プログラミングをしていないことに気づかされます。

コメント