【C#】連番付きの変数をループで処理したい。
- 評価
- クリップ 2
- VIEW 21K+
前提・実現したいこと
C#プログラミングにおいて、
連番付きの変数があるとします。(string a1, string a2…など)
そもそもこんな変数の宣言をせずに、配列とか使えという話ですが、
どうしてもこういった実装を行わなければならない事態が発生しているので、そこは保留してください。
この連番の変数を、ループで回して1つずつ値を取得したいと考えています。
この連番はa1 ~ a99まであります。
string a1 = "AAA";
string a2 = "BBB";
・
・
・
string a99 = "ZZZ";
そういったことは出来るでしょうか?
また、出来るとしたらどのような方法・コードの書き方をすればよいでしょうか。
C#初心者です。
宜しくお願い致します。
【追記】
(修正依頼内容1)
失礼いたしました。
クラス/構造体のメンバです。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+2
リフレクションで実装する方法と、愚直に書いておく方法の2パターンがあると思います。
// リフレクション
// 今回はリフレクションにFastMemberを使います。
// リフレクションは遅いため、何等かの方法でキャッシュしておくことが望ましいです
// とりあえず既成の外部クラスを使います。nuget からFastMemberを探して使ってみてください。
// FastMemberはクラスのアクセサ/ゲッタを生成してキャッシュしてくれるライブラリです。
IEnumerable<string> AsEnumerable()
{
var accessor = TypeAccessor.Create(typeof(/*型*/));
for (int i = 1; i < 99; ++i)
{
// 左側にリフレクションによって読み取りたいオブジェクト
// 右側にメンバーの名前を入れます
// クラスにメソッドを実装する場合を想定して今回は左側にthis、右側はメンバ名です。
yield return (string)accessor[this, $"a{i}"];
}
}
// 拡張メソッド版
public static IEnumerable<string> AsEnumerable(this /*型*/ obj)
{
var accessor = TypeAccessor.Create(obj.GetType());
for (int i = 1; i < 99; ++i)
{
yield return (string)accessor[obj, $"a{i}"];
}
}
リフレクションにした方が遅いので、ここだけ特別っていうなら愚直に書いておいた方がいいです。
以下のようになるのでコード自体は長いですが、難しいこともありませんし…
// 愚直な方法1(こちらは拡張メソッドとしても実装しやすく元クラスを弄らなくとも良い)
IEnumerable<string> AsEnumerable()
{
yield return a1;
yield return a2;
yield return a3;
yield return ...
yield return a99;
}
// 愚直な方法2(自然な形式で読み書きできる。)
public string this[int index]
{
get
{
switch (index)
{
case 0: return a1;
case 1: return a2;
case 2: return a3;
// ....
case 98: return a99;
default:
throw new IndexOutOfRangeException();
}
}
set
{
switch (index)
{
case 0: a1 = value; break;
case 1: a2 = value; break;
case 2: a3 = value; break;
// ....
case 98: a99 = value; break;
default:
throw new IndexOutOfRangeException();
}
}
}
追記
オマケ。コピペで使える全文です。
リフレクション
using FastMember;
using System;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
var sample = new ReflectionSample();
foreach (var str in sample.AsEnumerable())
{
Console.WriteLine(str);
}
Console.ReadKey();
}
}
public class ReflectionSample
{
public string a1 = "AAA";
public string a2 = "BBB";
public string a3 = "CCC";
}
public static class ReflectionSampleExtension
{
public static IEnumerable<string> AsEnumerable(this ReflectionSample obj)
{
var accessor = TypeAccessor.Create(typeof(ReflectionSample));
for (int i = 1; i < 3; ++i)
{
yield return (string)accessor[obj, $"a{i}"];
}
}
}
直書き
using System;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
var sample = new Sample();
foreach (var str in sample.AsEnumerable愚直1())
{
Console.WriteLine(str);
}
foreach (var str in sample.AsEnumerable愚直2())
{
Console.WriteLine(str);
}
Console.ReadKey();
}
}
public class Sample
{
public string a1 = "AAA";
public string a2 = "BBB";
public string a3 = "CCC";
// 愚直1
public IEnumerable<string> AsEnumerable愚直1()
{
yield return a1;
yield return a2;
yield return a3;
}
public string this[int index]
{
get
{
switch (index)
{
case 0: return a1;
case 1: return a2;
case 2: return a3;
// ....
// case 98: return a99;
default:
throw new IndexOutOfRangeException();
}
}
set
{
switch (index)
{
case 0: a1 = value; break;
case 1: a2 = value; break;
case 2: a3 = value; break;
// ....
// case 98: a99 = value; break;
default:
throw new IndexOutOfRangeException();
}
}
}
public IEnumerable<string> AsEnumerable愚直2()
{
for (int i = 0; i < 3; ++i)
{
yield return this[i];
}
}
}
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+1
int iでループさせつつ
指定した変数名の変数を取得を使いアクセスすればいけると思います。
for(int i = 1;i<100;i++){
var ikey = "a" + i.toString();
・・・
}
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+1
VS2015以降ならnameofで変数名を文字列として取得できるので取得した文字列をキーにしたDictionaryを用意するという手が使えるかも
var dic = new Dictionary<string, hogehoge>();
dic.Add(nameof(a1), a1);
~中略~
dic.Add(nameof(a99), a99);
int i= 0;
// ループで初期値を代入(次の行をループの中に書く)
dic[$"a{i}"] = new hogehoge(){ho = "ho", ge = "ge"};
// 以下は実際に取り出すぱてぃーん
textbox1.Text = dic[$"a{i}"].ho.ToString();
眠くてかなり端折ってるから使いたいように改変でおk
作ったdic自体をローカル変数でなくどこかのプロパティやプライベート変数で確保しておけばクラスのコンストラクタでDictionaryに格納すればいいと思う
でも、本人も書いてる通りこんな作りになってる時点で再設計したほうがいいと思う
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.13%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正、ベストアンサー選択の依頼
haru666
2017/01/27 10:26 編集
変数ってローカル変数ですか?それともクラス/構造体のメンバですか?