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

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

新規登録して質問してみよう
ただいま回答率
85.35%
C#

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Q&A

解決済

3回答

1318閲覧

C# 参照をする時の変数で取得する方法

nikinikiniki-ta

総合スコア15

C#

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

0グッド

0クリップ

投稿2021/11/30 08:14

お世話になります。現在変数でプロパティを取得する方法がないか調べているのですが、上手くいっておりません。
アドバイスを頂けましたら有難いです。

C#

1 public static class Message 2 { 3 public static readonly string Message1 = "ok"; 4 public static readonly string Message2 = "ng"; 5}

C#

1他クラス 2var Choice = "1" 3MessageBox.Show(Message + Choice);//このように変数で指定したmessageを取得したいです。

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2021/11/30 22:06 編集

上のコードのクラス定義の中にあるのはプロパティではなくてフィールドと言います。 > MessageBox.Show(Message + Choice);//このように変数で指定したmessageを取得したいです。 そういうことはできないので別の手段を考えましょう。String の配列にして添え字で取得するとか。
Zuishin

2021/11/30 09:44

var messages = new[] { "ok", "ng" }; var choice = 1; MessageBox.Show(messages[choice - 1]);
dodox86

2021/11/30 10:14

C# に限らず、変数名を文字列でアクセスしたいとする質問は頻出ですね。 teratailトップページにて: [C# 文字列 変数 アクセス] の検索結果: 242件
退会済みユーザー

退会済みユーザー

2021/11/30 23:49

初心者だとListやDictionary等のコレクションクラスの存在を知らないから、そういう思考になってしまうのかなと想像したり。
guest

回答3

0

質問のコメントにも書きましたが、質問の Message クラス定義の中にあるのはプロパティではなくてフィールドと言います。

MessageBox.Show(Message + Choice);//このように変数で指定したmessageを取得したいです。

そういうことはできないので別の手段を考えましょう。String の配列にして添え字で取得するとか。

例えば以下のように Message1 と Message2 の配列を返すパブリックプロパティを定義して、

// 静的クラスで String 型の配列を返すパブリック // プロパティ定義して利用 public static class Message { // フィールドを public にするのはお勧めしません private static readonly string Message1 = "ok"; private static readonly string Message2 = "ng"; // パブリックプロパティを定義 public static string[] Messages { get { return new String[] { Message1, Message2 }; } } }

それを以下のように利用してはいかがですか?

MessageBox.Show(Message.Messages[0]); MessageBox.Show(Message.Messages[1]);

以下はお勧めはしませんが・・・

Message.Messages[0] のような形にするのが気に入らないとか、どうしても Massage + index という形にしたいなら、Message クラスをインスタンスクラスとして定義してインデクサを使うとか、演算子 + をオーバーロードするとかいう方法もあります。以下のような感じ。

using System; namespace ConsoleAppOverload { internal class Program { static void Main(string[] args) { // インスタンスクラスにしてインデクサを定義 // または演算子 + をオーバーロード var message = new Message(); // インデクサ Console.WriteLine("-----インデクサ-----"); for (int index = 1; index < 4; index++) { Console.WriteLine(message[index]); } // 演算子 + オーバーロード Console.WriteLine("-----演算子オーバーロード-----"); for (int index = 1; index < 4; index++) { Console.WriteLine(message + index); } } } // インスタンスクラスにしてインデクサを定義 // または演算子 + をオーバーロード public class Message { // フィールドを public にするのはお勧めしません private static readonly string Message1 = "ok"; private static readonly string Message2 = "ng"; // インデクサを定義 public string this[int index] { get { if (index == 1) return Message1; else if (index == 2) return Message2; else return "未定義"; } } // 演算子 + をオーバーロード public static string operator +(Message msg, int index) { if (index == 1) return Message1; else if (index == 2) return Message2; else return "未定義"; } } }

結果は:

イメージ説明

投稿2021/12/01 01:30

編集2021/12/01 01:48
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

0

ベストアンサー

とりあえず、プロパティとフィールドを間違えてると思います。
リフレクション使えば出来ると言えば出来ますけど、普通にアクセスするより面倒だし速度も非常に遅くなります。

C#

1using System; 2using System.Reflection; 3 4public static class Message 5{ 6 public static readonly string Message1 = "ok"; // これはフィールド 7 public static string Message2 { get; } = "ng"; // これがプロパティ 8} 9 10class Program 11{ 12 static void Main() 13 { 14 var choice = "1"; 15 var fieldMessage1 = typeof(Message).GetField( 16 "Message" + choice, 17 BindingFlags.Static | BindingFlags.Public); 18 19 Console.WriteLine(fieldMessage1.GetValue(null)); // okが出力される 20 21 choice = "2"; 22 var propMessage2 = typeof(Message).GetProperty( 23 "Message" + choice, 24 BindingFlags.GetProperty | BindingFlags.Static | BindingFlags.Public); 25 26 Console.WriteLine(propMessage2.GetValue(null)); // ngが出力される 27 28 Console.ReadKey(); 29 } 30}

文字列で値を持ってくるならDictionaryがありますし、別に文字列である必要が無いなら、配列やListもあります。

cs

1using System; 2using System.Collections.Generic; 3 4class Program 5{ 6 private static readonly string[] _ArrayMessage = 7 { 8 "ok", 9 "ng", 10 }; 11 12 private static readonly Dictionary<string, string> _DictMessage = new Dictionary<string, string>() 13 { 14 {"Message1", "ok"}, 15 {"Message2", "ng"}, 16 }; 17 18 static void Main() 19 { 20 Console.WriteLine(_ArrayMessage[0]); 21 Console.WriteLine(_DictMessage["Message1"]); 22 23 Console.ReadKey(); 24 } 25}

リフレクションの速度が非常に遅いと言われても、どれくらい遅いのかピンと来ないと思うので、BenchmarkDotNet の計測結果を載せておきます。

cs

1using BenchmarkDotNet.Attributes; 2using BenchmarkDotNet.Diagnosers; 3using BenchmarkDotNet.Running; 4using System.Collections.Generic; 5using System.Reflection; 6 7public static class Message 8{ 9 public static string Message1 { get; } = "ok"; 10 public static string Message2 { get; } = "ng"; 11} 12 13//計測用テストクラス 14[MemoryDiagnoser(false)] 15[ShortRunJob] 16public class Test 17{ 18 private static readonly string[] _ArrayMessage = 19 { 20 "ok", 21 "ng", 22 }; 23 24 private static readonly Dictionary<string, string> _DictMessage = new Dictionary<string, string>() 25 { 26 {"Message1", "ok"}, 27 {"Message2", "ng"}, 28 }; 29 30 private int _Index = 0; 31 private string _StringKey = "1"; 32 33 [Benchmark] 34 public string UseReflection() 35 { 36 var prop = typeof(Message).GetProperty( 37 "Message" + _StringKey, 38 BindingFlags.GetProperty | BindingFlags.Static | BindingFlags.Public); 39 40 return (string)prop.GetValue(null); 41 } 42 43 [Benchmark] 44 public string UseArray() => _ArrayMessage[_Index]; 45 46 [Benchmark] 47 public string UseDictionary() => _DictMessage["Message" + _StringKey]; 48} 49 50class Program 51{ 52 static void Main() 53 { 54 BenchmarkRunner.Run<Test>(); 55 } 56} 57 58(計測結果) 59| Method | Mean | Error | StdDev | Median | Allocated | 60|-------------- |------------:|-----------:|----------:|------------:|----------:| 61| UseReflection | 202.8417 ns | 13.9314 ns | 0.7636 ns | 203.0229 ns | 48 B | 62| UseArray | 0.0055 ns | 0.1723 ns | 0.0094 ns | 0.0000 ns | - | 63| UseDictionary | 47.3129 ns | 9.5924 ns | 0.5258 ns | 47.3259 ns | 48 B |

投稿2021/11/30 08:46

編集2021/12/01 01:52
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

退会済みユーザー

退会済みユーザー

2021/11/30 08:58

個人的には、リフレクションが有効なケースはかなり稀で、むしろ速度やデバッグに悪影響を与える事の方が多いと思っているので、出来れば使わずに済ませるデータ構造を考えた方がよろしいかと思います。
guest

0

リフレクションを使ってみては?

C#

1using System; 2using System.Reflection; 3 4public static class Message 5{ 6 public static readonly string Message1 = "ok"; 7 public static readonly string Message2 = "ng"; 8 9 public static string GetValue(string index) { 10 FieldInfo fieldInfo = typeof(Message).GetField(index, 11 BindingFlags.Public | BindingFlags.Static); 12 if (fieldInfo == null) { 13 throw new ArgumentOutOfRangeException(); 14 } 15 return (string)fieldInfo.GetValue(null); 16 } 17}

C#

1var msg1 = Message.GetValue("Message1"); // ok 2var msg2 = Message.GetValue("Message2"); // ng

"1" とか "2" を引数にするなら GetField の第1引数を "Message" + index とかにしてください。

投稿2021/11/30 08:45

KOZ6.0

総合スコア2707

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問