こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

C#で変数名の取得

C#2.0を使っています。

例えば
string s = "test";
という変数名「s」があったときに、この変数名を
Reflectionか何かを利用して取得することはできないでしょうか?

s.GetType().NameなどでString(型)は取得できるのですが
変数名「s」を取得したいのです。

投稿日時 - 2009-02-11 21:38:52

QNo.4709361

すぐに回答ほしいです

質問者が選んだベストアンサー

変数といえば、「フィールド」「引数」「ローカル変数」がありますがどれでしょうか?
私の調べた範囲では、

「フィールド」は可能
「引数」はNameからインスタンスが取れないので無理
「ローカル変数」はNameも取れないので無理(コンパイルした時点で名前を保持していない?)


namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
(new myClass()).foo("引数");
}
}

class myClass
{
string s1 = "フィールド";

public void foo(string s2)
{
string s3 = "ローカル変数";

//フィールドの情報
FieldInfo[] fields = this.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
foreach (FieldInfo field in fields) {
object v = field.GetValue(this);
Console.WriteLine("[field]" + field.Name + "=" + v +"," + (v == (object)s1));
}

//引数の情報
ParameterInfo[] parameters = MethodBase.GetCurrentMethod().GetParameters();
foreach (ParameterInfo parameter in parameters) {
Console.WriteLine("[parameter]" + parameter.Name);
}

//ローカル変数の情報
IList<LocalVariableInfo> localVariables = MethodBase.GetCurrentMethod().GetMethodBody().LocalVariables;
foreach (LocalVariableInfo localVariable in localVariables) {
Console.WriteLine("[localVariable]" + localVariable.LocalType);
}
}
}
}

投稿日時 - 2009-02-13 12:18:16

補足

 public class Debugger
 {
  static protected List<Abstract> writers = new List<Abstract>();
  static private string indent = "\t";
  static public string Indent
  {
   get { return indent; }
   set { indent = value; }
  }

  static public void Dump(object src)
  {
   #region "デフォルトでライターの追加"

   StringBuilder output = new StringBuilder();
   output.Append(RecursiveGetBuffer(src, 0, -1));

   foreach (Abstract writer in writers)
   {
    // System.Windows.Forms.MessageBox.Show(output.ToString());
    // System.Console.WriteLine(output.ToString());
    // など
    writer.Write(output.ToString());
   }
  }

  static public void AddWiter(Abstract writer)
  {
   writers.Add(writer);
  }
  static private string GetMultiIndent(int count)
  {
   string s = "";
   for (int i = 0; i < count; i++)
   {
    s += Indent;
   }
   return s;
  }
  static private string GetFormatType(object obj)
  {
   return "[" + obj.GetType().ToString() + "] => ";
  }

  static private string RecursiveGetBuffer(object src, int recursive, int index)
  {
   StringBuilder output = new StringBuilder();

   if (src == null)
   {
    // 本当は型情報などを取得して表示したいけど、nullなのでやむおえず
    output.Append(GetMultiIndent(recursive) + " null" + Environment.NewLine);
   }
   else
   {
    Type type = src.GetType();
    if (type.IsPrimitive || type == typeof(string) || type.IsEnum)
    {
     if (index < 0)
     {
      output.Append(GetMultiIndent(recursive) + GetFormatType(src) + src + Environment.NewLine);
     }
     else
     {
      // 配列の中身を表示する場合
      output.Append(GetMultiIndent(recursive) + "[" + index + "]" + " => " + src + Environment.NewLine);
     }
    }
    else
    {
     output.Append(GetMultiIndent(recursive) + GetFormatType(src) + Environment.NewLine + GetMultiIndent(recursive) + "(" + Environment.NewLine);

     if (type.IsArray)
     {
      int n = 0;
      foreach (object temp in (Array)src)
      {
       recursive++;
       output.Append(RecursiveGetBuffer(temp, recursive, n));
       recursive--;
       n++;
      }
     }
     else if (type.IsGenericType)
     {
      int n = 0;
      #region "C#2.0では動的型がないためそれぞれの型を用意する。C#4.0で可能?"
      List<string> stringSrc = src as List<string>;
      List<int> intSrc = src as List<int>;
      if (stringSrc != null)
      {
       foreach (object temp in stringSrc)
       {
        recursive++;
        output.Append(RecursiveGetBuffer(temp, recursive, n));
        recursive--;
        n++;
       }
      }
      else if (intSrc != null)
      {
       foreach (object temp in intSrc)
       {
        recursive++;
        output.Append(RecursiveGetBuffer(temp, recursive, n));
        recursive--;
        n++;
       }
      }
      #endregion
     }
     else if (type.IsClass)
     {
      recursive++;
      foreach (FieldInfo fi in type.GetFields())
      {
       object value = fi.GetValue(src);
       output.Append(RecursiveGetBuffer(value, recursive, -1));
      }
      recursive--;
     }

     output.Append(GetMultiIndent(recursive) + ")" + Environment.NewLine);
    }
   }

   return output.ToString();
  }
 }

投稿日時 - 2009-02-13 19:59:59

お礼

ご返答ありがとうございます。
取得したいのは引数だと思います。
すいません、お題から逸れるかもしれませんが、
そもそもなんで変数名を取得したいと思ったかというと、
PHPでいうvar_dump関数のような、
変数やクラスや配列などを引数に渡して表示してくれる関数を
C#でも作りたいと思ったからです(var_dumpもローカル変数名などは表示されませんけど・・・)
一応探したりしたのですが似たような機能はなかったので、
VisualStadioのデバッグの変数表示機能も使ってみたのですが、
見易さと使い勝手から、やっぱりvar_dumpのような一発で全体像が見えるような
機能がほしいと思いました。
そこで自分なりに考えてみたのですが、

※クラスの定義は補足を参考にしてください

string s1 = "test";
Debugger.Dump(s1);
List<int> list = new List<int>();
list.Add(11);
list.Add(22);
Debugger.Dump(list);
TestClass tc = new TestClass();
tc.a = 1;
tc.testClass = new TestClass();
tc.testClass.a = 2;
Debugger.Dump(tc);

型を気にせず引数に渡して展開された変数を表示します。
申し訳ないのですが、このようなことをふまえて
アドバイス頂けないでしょうか?
代わりになるやり方(関数)など知っていましたら教えてもらいたいです。

投稿日時 - 2009-02-13 20:03:00

ANo.1

このQ&Aは役に立ちましたか?

1人が「このQ&Aが役に立った」と投票しています

回答(2)

ANo.2

http://oshiete1.goo.ne.jp/qa4173884.html

投稿日時 - 2009-02-13 21:25:27

お礼

ご返答ありがとうございます。
なるほど、同じような質問があったんですね・・・
試してみましたが、たしかに多次元配列はエラーがでましたが
ジャグ配列は大丈夫でした。
あとはこのやり方を利用して自分なりにカスタマイズ(インデントの幅を調節できたりしたら理想ですね)
していきたいと思います。参考になりました。

投稿日時 - 2009-02-14 03:11:09