MRが楽しい

MRやVRについて学習したことを書き残す

EnumerableのOfTypeを使って型を指定して要素のシーケンスを取得する

本日は C# の小ネタ枠です。
Enumerable の OfType を使って型を指定して要素のシーケンスを取得する方法について記事に残します。

OfTypeメソッド

OfType は指定した型で要素をフィルタ処理して返します。
learn.microsoft.com

動作確認

ベースクラスと幾つかの継承クラスを作成しました。
ボールと人形クラスはおもちゃクラスを継承し、お肉クラスは食べ物クラスを継承しています。
またおもちゃクラスと食べ物クラスは同じアイテムクラスを継承しています。
・ItemBase.cs(アイテムクラス)

public abstract class ItemBase
{
    public string Type;
    public string Name;
}

・ToyBase.cs(おもちゃクラス)

public abstract class ToyBase : ItemBase
{
    // ご機嫌アップ率
    public int HumourUp;

    protected ToyBase()
    {
        Type = "Toy";
    }
}

・FoodBase.cs(食べ物クラス)

public abstract class FoodBase : ItemBase
{
    // 空腹アップ率
    public int HungerUp;
    
    protected FoodBase()
    {
        Type = "Food";
    }
}

・BallToy.cs(ボールクラス)

public sealed class BallToy : ToyBase
{
    public BallToy() : base()
    {
        Name = "Ball";
        HumourUp = 10;
    }
}

・DollToy.cs(人形クラス)

public sealed class DollToy : ToyBase
{
    public DollToy() : base()
    {
        Name = "Doll";
        HumourUp = 10;
    }
}

・MeetFood.cs(お肉クラス)

public sealed class MeetFood : FoodBase
{
    public MeetFood() : base()
    {
        Name = "Meet";
        HungerUp = 10;
    }
}

これらのクラスを登録したリストに対して OfType でベースクラスを指定して取り出してみます。
・OfTypeTest.cs

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class OfTypeTest : MonoBehaviour
{
    void Start()
    {
        ArrayList objectList = new();
        objectList.Add(new BallToy());
        objectList.Add(new DollToy());
        objectList.Add(new MeetFood());

        var itemNameList = objectList
            .OfType<ItemBase>() // ItemBase型で取得する
            .Select(item => item.Name) // 名前を文字として抽出する
            .Aggregate((connectionPhrase, name) => $"{connectionPhrase} {name}"); // 全てを結合した文字列で出力する
        Debug.Log($"ItemNameList : {itemNameList}");
        
        var toyNameList = objectList
            .OfType<ToyBase>() // ToyBase型で取得する
            .Select(item => $"{item.Name}:{item.HumourUp}") // 名前とご機嫌アップ率を文字として抽出する
            .Aggregate((connectionPhrase, data) => $"{connectionPhrase} {data}"); // 全てを結合した文字列で出力する
        Debug.Log($"ToyNameList : {toyNameList}");
    }
}

以下の通り、クラスが合致するものだけが取得できていることが確認できます。
また、OfType で型の変換も行われるため、指定クラスのプロパティにもアクセスできています。