🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

LINQ

LINQとはLanguage INtegrated Queryの略で、「統合言語クエリ」という意味です。C#やVisual Basicといった言語のコード内に記述することができるクエリです。

Q&A

解決済

3回答

7191閲覧

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

Y0241-N

総合スコア1066

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

LINQ

LINQとはLanguage INtegrated Queryの略で、「統合言語クエリ」という意味です。C#やVisual Basicといった言語のコード内に記述することができるクエリです。

0グッド

0クリップ

投稿2019/12/25 06:56

編集2019/12/25 07:33

実現したいこと

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

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

該当のソースコード

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

cs

1 public class CustumData 2 { 3 public int Value{get; set;} 4 public int Quantity{get; set;} 5 public string ProductName{get; set;} 6 } 7 public List<CustumData> ProductList; 8 9 ProductListの中身は例として以下のような状態とする。 10 ProductList[0] = 5,10,pen 11 ProductList[1] = 2,7,desk 12 ProductList[2] = 8,45,watch 13 ProductList[3] = 14,3,sword 14 15 foreach(var a in ProductList) 16 { 17 各ProductList[n]の中身をすべて出力したい 18 } 19

試したこと

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

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

Unity 2019 1.41f

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

BluOxy

2019/12/25 07:12

「すでに複数の異なるCustuDataを持っているとする」という文の意味がよく分かりませんでした。 何が「異なる」のでしょうか。 各要素が持つメンバーの値が異なるだけなら、foreachでメンバーの中身にアクセスすれば良いだけです。 ProductListに入っている要素は全てCustomData、もしくはそれを継承したオブジェクトではないのでしょうか。 >独自クラスの要素数が増えた場合ひとつひとつを追記する手間があるためこれ以外の方法で一括で処理できればいいなぁと思っています。 これ以上省略は難しいと思いますが、例えばどういうノリでコードを書ければよいでしょうか。
BluOxy

2019/12/25 07:24

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

2019/12/25 07: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 07:32

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

回答3

0

ベストアンサー

最初に

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

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

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

回答

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

C#

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

投稿2019/12/25 07:37

編集2019/12/25 07:55
BluOxy

総合スコア2663

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

BluOxy

2019/12/25 07:44 編集

ただ、リフレクションを使うのは紹介しておいてあれですが、少し邪道な気がします。 仮にメンバーが数十個、数百個まで増えるケースがあれば、それはクラスの設計が悪いと思うので、YAmaGNZさんの仰る通り ToString() をオーバーライドして表示するよう作るのが良いと思います。
SHOMI

2019/12/25 07:52

細かいですが、GetValue(s無し)では?
BluOxy

2019/12/25 07:55

s無しですね。ご指摘ありがとうございます。
Y0241-N

2019/12/25 08:35

回答ありがとうございます。 私の認識の間違いまで訂正してくださってありがとうございます、とても勉強になりました。 以後は区別して使い分けていきます。 提示していただいたサンプルコードを試したところ、プロパティの中身を取り出すことが出来ました。 ただ、恐らくBluOxy様が想像されていた出力結果は「5/10/pen」のように一行で出力される形だと思いますが、実際の結果は「5」「10」「pen」と個別に出力されました。
YAmaGNZ

2019/12/25 10:04

内側のforeachを Debug.Log(string.Join("/", a.GetType().GetProperties().Select(x => x.GetValue(a).ToString()))); こんな感じで書いてやるとか
Y0241-N

2019/12/27 01:11 編集

アドバイスありがとうございます。 YAmaGNZ様のご提示いただいた方法を試してみたところ、上手く一列で出力できました。 ありがとうございます。 処理内容の確認なのですが、【 a.GetType().GetProperties()】でaの全てのプロパティの属性を取得し、さらにそれらを【.Select(x => x.GetValue(a)】で属性を値に変換し、文字に変換する。 という処理の流れと認識していますが、合っていますでしょうか?
YAmaGNZ

2019/12/27 01:34 編集

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

2019/12/27 01:30

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

2019/12/27 01:42

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

0

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

投稿2019/12/25 07:36

YAmaGNZ

総合スコア10469

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Y0241-N

2019/12/25 08:23

回答ありがとうございます。 > CustumDataクラスにToStringメソッドを実装したほうがいいのではないか この方法をとっている記事を何度か見ました、コスト的にそちらの方法の方が軽いのでしょうか? 恐らくそうだと思うのですが、実装して取り出す方法がよく分からなかった為、少し調べてみようと思います。
YAmaGNZ

2019/12/25 09:57

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

2019/12/25 09:59

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

0

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

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

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

投稿2019/12/25 07:32

y_waiwai

総合スコア88038

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Y0241-N

2019/12/25 08:20

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

2019/12/25 08:24

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問