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

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

詳細はこちら
C#

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

Q&A

解決済

5回答

3285閲覧

フラグとして使用できるように定義したenumの値を配列のindexとして使用する方法

sadada

総合スコア7

C#

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

0グッド

0クリップ

投稿2019/10/28 15:06

編集2019/10/28 15:15

C#の質問です。

フラグとして使用できるように定義した列挙型HogeTypeを、
下記コードのvalues[(int)HogeType2.Type3]のように配列のindexとして使用したいのですが、値が飛び飛びなので当然ながらできません。
values[(int)HogeType2.Type3]のように配列の値を直接取得までの速さはできなくとも、Dictinary<HogeType,float>よりも速い方法がありましたら教えていただきたいです。

(HogeTypeと1の論理積が1になるまでHogeTypeを右シフトして、右シフトした回数を配列のindexとする手法が最速でしょうか・・・)

よろしくお願いいたします。

cs

1public enum HogeType 2{ 3 Type1 = 1 << 0, 4 Type2 = 1 << 1, 5 Type3 = 1 << 2, 6} 7public enum HogeType2 8{ 9 Type1 = 0, 10 Type2, 11 Type3 12} 13 14public class HogeClass 15{ 16 public HogeClass() 17 { 18 float[] values = new float[] { 0.1f, 0.2f, 0.3f}; 19 20 float f = values[(int)HogeType.Type3]; // ←当然エラー 21 float f2 = values[(int)HogeType2.Type3]; 22 } 23} 24 25

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2019/10/28 15:28

配列のインデックスとして使いたいのに、値を飛び飛びにする理由は何でしょう?
sadada

2019/10/28 17:05

フラグとして使用できるようにするためとなります。
len_souko

2019/10/28 17:06

フラグとして使うとありますが、 HogeType.Type1 | HogeType.Type2 こういう場合はどう扱うんですか? 正直質問からは何のためにenumを使用するのか全く見えてきませんので、目的を忘れて手段に固執しているような予感しかしません
sadada

2019/10/28 18:13

クラスC1がフラグとして使用しないHogeType型の変数を持っている クラスC2がフラグとして使用しないHogeType型の変数を持っている クラスC1とクラスC2を型とするフィールドをそれぞれ持つクラスPが、C1,C2のHogeType型をFlag管理したい。 そしてHogeType型に紐付けた値を動的に切り替えたい(質問文のvalues) クラスPが持つC1とC2のHogeTypeに紐付けた値(values)の合計値をいくつか知りたい と思い質問いたしました(コードではなくわかりにくい文章ですみません)。 客観的に見て目的を忘れて手段に固執されているところがあればご指摘くださると幸いです。
Zuishin

2019/10/28 22:59 編集

それは目的ではなく手段です。目的の記述が皆無なので、目的を忘れて手段に固執しているように見えます。別の言い方をすれば、手段のことを目的だと思い込んでいるように見えます。
len_souko

2019/10/29 03:22

enumでフラグって書くからbitフラグかと思ったからの一つ目の疑問だったんですが、全く関係なさそうですね。「HogeType.Type1 | HogeType.Type2」を使用するなら「float[] values = new float[] { 0.1f, 0.2f, 0.3f};」なんてありえないけど言及がないので。 また、ひょっとしてこれが本来の目的?と思われるのは >Dictinary<HogeType,float>よりも速い方法がありましたら教えていただきたいです。 ですが、.NET4.6以前を使用している場合でもなければintをkeyにした場合と比べても気にする必要がないレベルの速さらしいのでDctionaryのkeyにenumを使うと遅いからってのは過去のことのようです ただ、Dctionary自体が遅いというのであれば、また別ですが、そのあたりも含めて質問に書いていないと質問で絞った範囲でしか回答が来ないので最善策にはたどり着けませんよ
sadada

2019/10/29 13:26

意図がわかりにくい質問文であったことは否めません。 失礼しました・・・
guest

回答5

0

このような感じで拡張メソッドを作ってはどうでしょう?
こうすれば、Enumのフラグで立つビットが順番でなくても対応できます。

C#

1 public enum HogeType 2 { 3 Type1 = 1 << 0, 4 Type2 = 1 << 1, 5 Type3 = 1 << 2, 6 Type4 = 1 << 4, 7 } 8 9 public static partial class EnumExtend 10 { 11 public static int GetIndex(this HogeType param) 12 { 13 switch (param) 14 { 15 case HogeType.Type1: 16 return 0; 17 case HogeType.Type2: 18 return 1; 19 case HogeType.Type3: 20 return 2; 21 case HogeType.Type4: 22 return 3; 23 } 24 return -1; 25 } 26 } 27 28 29 //使い方 30 //f2 = values[HogeType.Type2.GetIndex()];

投稿2019/10/28 16:03

YAmaGNZ

総合スコア10469

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

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

sadada

2019/10/28 17:02

拡張メソッドもありですね・・・! ありがとうございます!
guest

0

HogeTypeをindexとするように配列を用意すれば良い,とかいう方向はダメですか?

//てきとーにダミー要素を持たせた float[] values = new float[] { 0,0f, 0.1f, 0.2f, 0.0f, 0.3f};

投稿2019/10/29 04:09

fana

総合スコア11985

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

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

sadada

2019/10/29 13:35

そうですね・・・無理してenumでわざわざflag管理する必要はなかったかもしれません。 ありがとうございました。
guest

0

本来の目的が不明なので質問文から勝手に想像してみます
今回の質問のためにググった内容からenum + Dictionaryは遅いという前提で速い手段を使いたいということだと決めつけます
なお、.NET Framework 4.6からはDctionaryのkeyにenumを使ってもintをkeyに使うのとほぼ変わらない程度のやや遅いといった感じなので、実際に試して遅いから早くしようとしているものと勝手に決めつけると今どき.NET4.6以前しか使えないということはありえないだろうからDictionary + int keyですら遅いので速度を上げたいというのが本来の目的だと決めつけることができます

質問文に対するコメントで出てきた内容

クラスC1がフラグとして使用しないHogeType型の変数を持っている

クラスC2がフラグとして使用しないHogeType型の変数を持っている
クラスC1とクラスC2を型とするフィールドをそれぞれ持つクラスPが、C1,C2のHogeType型をFlag管理したい。
そしてHogeType型に紐付けた値を動的に切り替えたい(質問文のvalues)
クラスPが持つC1とC2のHogeTypeに紐付けた値(values)の合計値をいくつか知りたい

正直このフラグ管理というのがbitシフトしているからbitフラグかと思いましたが質問コメントで確認してもスルーされているのでHogeType.Type1 | HogeType.Type2といったbitフラグによる管理はしていないと思われます
※そもそもbitフラグを|でまとめる場合ならDictionaryのkeyにenumを使うとbitごとにばらして値を取得してリストなり合計値なりを算出する必要があるので

なんにせよ、enumの値を保持しているのはプロパティであるということはコメントで判別できました

で、ここから本題
一般的にenumでタイプを設定する回数よりもそこからタイプ別の値を取得する回数の方が多いと思われますので、タイプの設定時のコストが多少重くなってもタイプから値を取得する処理が軽い方が全体としての速度は上がると思います
また、値を取得するたびにタイプから値を算出するのが無駄かと思いますので、HogeTypeのプロパティのsetterの時に値を取得してprivateのフィールドにぶち込んでおき、getterしかない値を取得するプロパティ経由で参照すれば速くなると思います

C#

1 2 public class C1 3 { 4 private Dctionary<HogeType, float> dic = new Dctionary<HogeType, float> 5 { 6 HogeType.Type1 = 0.1f, 7 HogeType.Type2 = 0.2f, 8 HogeType.Type3 = 0.3f, 9 }; 10 11 public float V { get; private set; } 12 13 private HogeType type; 14 public HogeType Type 15 { 16 get { retrun type; } 17 set 18 { 19 type = value; 20 V = dic[value]; 21 } 22 } 23 } 24

投稿2019/10/29 03:53

len_souko

総合スコア1363

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

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

sadada

2019/10/29 13:29

タイプを設定する回数とタイプで値を取得する回数を考慮して優先を決めたいと思います。 ありがとうございました。
guest

0

HogeType を 0, 1, 2 に変換します。そうすれば配列の添え字として使えます。

C#

1using System; 2 3namespace ConsoleApp1 4{ 5 class Program 6 { 7 public enum HogeType 8 { 9 Type1 = 1 << 0, 10 Type2 = 1 << 1, 11 Type3 = 1 << 2, 12 } 13 14 static int HogeToInt(HogeType hoge) 15 { 16 return (int)Math.Log((int)hoge, 2); 17 } 18 19 static void Main() 20 { 21 foreach (var hoge in new[] { HogeType.Type1, HogeType.Type2, HogeType.Type3 }) 22 { 23 Console.WriteLine(HogeToInt(hoge)); 24 } 25 } 26 } 27}

投稿2019/10/28 16:06

編集2019/10/28 16:07
Zuishin

総合スコア28669

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

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

sadada

2019/10/28 17:04

いちいち右シフト云々で求めるのではなく、logですっきり求めることができるのを失念していました。 ありがとうございます!
guest

0

ベストアンサー

求められている回答からずれてしまうかもしれませんが、public enum HogeType2で宣言した列挙子を中心に考えて、フラグも配列として管理してはどうでしょうか

C#

1public enum HogeType2 2{ 3 Type1 = 0, 4 Type2, 5 Type3 6} 7 8public class HogeClass 9{ 10 public HogeClass() 11 { 12 13 float[] values = new float[] { 0.1f, 0.2f, 0.3f}; 14 int[] HogeFlg = new int[] { 1 << 0, 1 << 1, 1 << 2 }; 15 16 float f2 = values[(int)HogeType2.Type3]; 17 18 int x = XXXXXX; 19 if (x & HogeFlg[(int)HogeType2.Type3]) { 20 : 21 (なんかの処理) 22 : 23 } 24 } 25}

投稿2019/10/28 15:28

KoichiSugiyama

総合スコア3041

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

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

sadada

2019/10/28 17:01

フラグを配列として定義する発想はありませんでした・・・! ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問