質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.37%

【Unity】【C#】独自クラスの異なる型のすべての要素を楽に取り出して表示したい

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 3,654

score 622

実現したいこと

独自クラスをリスト化し、要素の追加等はできたのですが、要素を追加した後に内容を確認したいと思って
foreach文で各リストの独自クラスの中身を抜き出そうとしたのですが上手くいかずに困っています。

異なる型を持った独自クラスの中身をforeachのようにループ処理で抜き出すことは可能でしょうか?

該当のソースコード

例として以下のような独自クラスがあり、これをリスト化したProductListが複数の異なる要素を持っているとした場合、
どのようにすれば可能でしょうか。

    public class CustumData
    {
        public int Value{get; set;}
        public int Quantity{get; set;}
        public string ProductName{get; set;}
    }
    public List<CustumData> ProductList;

    ProductListの中身は例として以下のような状態とする。
    ProductList[0] = 5,10,pen
    ProductList[1] = 2,7,desk
    ProductList[2] = 8,45,watch
    ProductList[3] = 14,3,sword

    foreach(var a in ProductList)
    {
        各ProductList[n]の中身をすべて出力したい
    }

試したこと

Debug.Log(a.Value + " / " + a.Quantity + " / " + a.ProductName);
とすれば表示できるとは思いますが、独自クラスの要素数が増えた場合ひとつひとつを追記する手間があるため
これ以外の方法で一括で処理できればいいなぁと思っています。

補足情報(FW/ツールのバージョンなど)

Unity 2019 1.41f

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • BluOxy

    2019/12/25 16:12

    「すでに複数の異なるCustuDataを持っているとする」という文の意味がよく分かりませんでした。
    何が「異なる」のでしょうか。
    各要素が持つメンバーの値が異なるだけなら、foreachでメンバーの中身にアクセスすれば良いだけです。

    ProductListに入っている要素は全てCustomData、もしくはそれを継承したオブジェクトではないのでしょうか。

    >独自クラスの要素数が増えた場合ひとつひとつを追記する手間があるためこれ以外の方法で一括で処理できればいいなぁと思っています。
    これ以上省略は難しいと思いますが、例えばどういうノリでコードを書ければよいでしょうか。

    キャンセル

  • BluOxy

    2019/12/25 16:24

    foreach という単語が出ているので foreach で各要素の中身を表示する方法を聞いているのかと思っていましたが、真の質問は「オブジェクトが持つ全てのメンバーの値を楽に表示する方法がないか」ということで良いでしょうか?

    キャンセル

  • Y0241-N

    2019/12/25 16:24

    質問ありがとうございます、分かりにくい表現ですみません。
    >「すでに複数の異なるCustuDataを持っているとする」という文の意味がよく分かりませんでした。
    私が考えていた意味は以下のような状態です。

    ProductList[0]の中身は5,10,pen
    ProductList[1]の中身は2,7,desk
    ProductList[2]の中身は...etc
    という風にデータが入っている状態を想定しています。

    なのでProductListはすべてCustuDataを継承しています。

    >これ以上省略は難しいと思いますが、例えばどういうノリでコードを書ければよいでしょうか。

    理想的な形はCustuData内の要素が増えた際にも、出力部分は追記なしで対応できればと思っています。
    なのでループ処理で表記できないものかと思い、質問させていただきました。

    以下はこうしたいという理想のコードです。
    foreach(var a in ProductList)
    {
    foreach(var aa in a)
    {
    Debug.Log(aa);
    }
    }

    キャンセル

  • Y0241-N

    2019/12/25 16:32

    >真の質問は「オブジェクトが持つ全てのメンバーの値を楽に表示する方法がないか」ということで良いでしょうか?
    そうですね、独自クラスの異なる型のすべての要素を楽に取り出して表示できるか、というところが知りたいです。

    キャンセル

回答 3

checkベストアンサー

+1

最初に

理想的な形はCustuData内の要素が増えた際にも
独自クラスの異なる型のすべての要素を楽に取り出して表示できるか

おそらく、Y0241-Nさんが仰っている「要素」とはメンバーのことではないでしょうか。
もう少し細かく書くとpublic int Value{get; set;}という書き方はメンバーの中でもプロパティと呼びます。

なので、質問は「オブジェクトが持つ全プロパティの値を表示する方法がないか」だと認識して回答します。
※「配列の要素」と「クラスのメンバー」は別物なので分けて使いましょう。

回答

リフレクションという機能を使ってそのクラスに何のプロパティが定義されているかを動的に取得することができます。
デバッグはしていませんが、下記がリフレクションを使ったサンプルコードです。

foreach (var a in ProductList) {
  foreach(var property in a.GetType().GetProperties()){
    Debug.Log(string.Join("/",property.GetValue(a).ToString()));
  }
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/12/27 10:25 編集

    a.GetType().GetProperties()でaの型の全てのプロパティを列挙して
    .Selectにてその列挙したプロパティ全てに対して
    「x.GetValue(a).ToString()」にてaのインスタンスで保持しているプロパティの値を取得して文字列として返すことを行い、その結果をIEnumerableとして返す。
    それをstring.Joinによって”/”で連結して1つの文字列とする。
    といった感じですね
    やっていることはBluOxyさんの回答のforeachで記述されていることとほぼ同じです。
    プロパティの値を取得した結果を配列とし、string.Joinに渡している部分だけが異なることになります。

    キャンセル

  • 2019/12/27 10:30

    あと、現状考えられているプロパティが基本型だけみたいですのでRefrectionを使用した形でもいいのですが、プロパティに独自クラス等のToStringでデータの値が理解できるような文字列で返してくれないものがあった場合に面倒なことになるかと思います。

    キャンセル

  • 2019/12/27 10:42

    返答ありがとうございます。
    詳細な流れを書いていただいたおかげで理解が深まりました、注意点に関してもアドバイスありがとうございます。プロパティに基本型以外を実装する際は注意します。

    キャンセル

+1

Refrectionを使えば思っていることは可能だと思います。
ただ、そこまでの労力をかけるべきなのか?という疑問はあります。
そうするのであれば、CustumDataクラスにToStringメソッドを実装したほうがいいのではないかと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/12/25 17:23

    回答ありがとうございます。
    > CustumDataクラスにToStringメソッドを実装したほうがいいのではないか

    この方法をとっている記事を何度か見ました、コスト的にそちらの方法の方が軽いのでしょうか?
    恐らくそうだと思うのですが、実装して取り出す方法がよく分からなかった為、少し調べてみようと思います。

    キャンセル

  • 2019/12/25 18:57

    Refrectionと比べた場合、Refrectionのほうが重いです。

    キャンセル

  • 2019/12/25 18:59

    実装は
    public override string ToString()
    {
    return "表示したい形式で返す";
    }
    という感じでoverrideしてやればいいです。

    キャンセル

0

求めてることと違うかもだけど、手を抜きたいなら、XMLでシリアライズしたものを出せばいいんじゃないかと

XmlSerializerを使ってシリアライズ/デシリアライズするには?[C#/VB]:.NET TIPS - @IT

#Unityで使えるかどうか。。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/12/25 17:20

    回答ありがとうございます。
    シリアライズに関しての知識がない上で参考URLを基に試してみましたが、シリアライズする為には
    StreamWriterが必要となるようで上手くいきませんでした。

    キャンセル

  • 2019/12/25 17:24

    もともとクラスのナカミをファイルに保存する用途なので、やるとしたらメモリに展開してそれを出力するってテでしょうけどねえ

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.37%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る