none
Можно ли получить имя переменной-элемента массива в виде строки? RRS feed

  • Вопрос

  • Добрый день!

    Собственно, вопрос. Мне нужно любым способом узнать имя переменной из массива, переданной в функцию.

    Задача примерно такая:

    MyClass Var1 = new MyClass(); MyClass Var2 = new MyClass(); MyClass Var3 = new MyClass(); 

    void ViewName(MyClass myVar){ myVar.Name = /* некий код для получения имени переменной*/ ;}

    MyClass [] mcArr = {Var1, Var2, Var3};

    public void ViewArr()

    { foreach (MyClass mc in mcArr)

    ViewName(mc);

    }

    Возможно ли узнать ИМЕНА переменных, занесённых в массив? Может, не в функции (я набросал этот код просто для наглядности), а через Type, макросы или ещё что-то... Любым способом.

    В общем, имя исходной переменной должно сохраняться внутри неё же.

    Заранее большое спасибо!


    • Изменено SvarogichRed 6 февраля 2013 г. 10:43
    6 февраля 2013 г. 10:40

Ответы

  • Можно извратиться следующим образом:

    using System;
    using System.Linq.Expressions;
    
    namespace ConApp
    {
        public class MyClass { }
    
        public class Program
        {
            static string GetName<T>(Expression<Func<T>> expr)
            {
                var member = ((MemberExpression)expr.Body).Member;
                return member.Name;
            }
    
            static void Main(string[] args)
            {
                MyClass Var1 = new MyClass();
                MyClass Var2 = new MyClass();
                MyClass Var3 = new MyClass();
    
                MyClass[] mcArr = { Var1, Var2, Var3 };
    
                foreach (MyClass mc in mcArr)
                    Console.WriteLine(GetName(() => mc));
    
                Expression<Func<MyClass>>[] exprArr = { () => Var1, () => Var2, () => Var3 };
    
                foreach (var expr in exprArr)
                    Console.WriteLine(((MemberExpression)expr.Body).Member.Name);
            }
        }
    }


    В данном примере в первом цикле будут выводиться имена именно той переменной, что поступает на вход метода GetName, а именно: mc.

    Во втором случае я заношу в массив выражения (лямбды), таким образом сохраняются имена изначальных переменных, и именно они будут выведены в дальнейшем: Var1, Var2, Var3.

    Оно?

    P.S. при необходимости использовать в дальнейшем выражения из exprArr, можно компилировать их методом Compile().

    ----

    Пока писал сообщение, проблема решена автором. Но что-то решение не соответствует поставленному вопросу.

    • Изменено Petalvik 6 февраля 2013 г. 12:19
    • Помечено в качестве ответа SvarogichRed 7 февраля 2013 г. 3:19
    6 февраля 2013 г. 12:16
  • можно пойти други путем, создать Hash<string,object> и записывать в него имя переменно и знаение переменно
    • Помечено в качестве ответа SvarogichRed 6 февраля 2013 г. 11:26
    6 февраля 2013 г. 11:17

Все ответы

  • Несовсем понятен ваш вопрос, вам надо узнать как называлась переменная д того как она была помещена в массив и переданна в функцию?

    6 февраля 2013 г. 10:43
  • Имя переменной - это эфимерность, которая существует только во время написания программы. Поэтому если коротко, то узнать ее никак нельзя.
    6 февраля 2013 г. 11:06
    Отвечающий
  • Я согласен, но в классическом VС++ был, если не ошибаюсь, макрос __FUNCTION__ , который узнавал у компилятора имя текущей функции. Им можно было пользоваться в runtime. Что-то аналогичное и для переменых было.

    Компилятор (или линкер) где-то складывают список имен переменных и соотвествующих им адресов памяти. Теоретически можно достать.

    6 февраля 2013 г. 11:12
  • Да, желательно знать исходное имя. В данном примере - это "Var1",  "Var2",  "Var3".

    Собственно, если это невозможно - я найду другие пути реализации своей задумки. Но хотелось бы знать, есть ли в принципе в C# возможность получения имен идентификаторов...

    6 февраля 2013 г. 11:14
  • можно пойти други путем, создать Hash<string,object> и записывать в него имя переменно и знаение переменно
    • Помечено в качестве ответа SvarogichRed 6 февраля 2013 г. 11:26
    6 февраля 2013 г. 11:17
  • В C# есть замечательный механизм который называется Reflection. Он позволяет делать всякие нехорошие вещи. Например, имея переменную некоего типа, про который вы ничего не знаете, узнать какие поля/свойства/методы/события у этого объекта есть. И мало того, что вы можете об этом узнать, вы их даже можете вызвать. Но узнать имя переменной - нельзя.

    6 февраля 2013 г. 11:19
    Отвечающий
  • Спасибо. С Reflection немного знаком, но что с ним можно вызывать методы - не знал.

    Ладно, я решил свой вопрос иначе.

    enum awPanels { awButtonPanel, awDirectory, awCollection, awPreviewOut, awPreviewIn }; static string GetPanelName(awPanels p) { return p.GetType().GetEnumName(p); } ViewSaveInfo GetPanelVSI(awPanels p) { foreach (ViewSaveInfo vsi in vsiArr) if (vsi.PositionPane == GetPanelName(p)) return vsi; return null; } List<ViewSaveInfo> vsiArr = new List<ViewSaveInfo>(); void AddGridToPanel(Grid srcGrid, awPanels destPanel) { ViewSaveInfo vsi = new ViewSaveInfo<Grid>(null, SaveInfo) { PositionPane = GetPanelName(destPanel) };

    /* ... */

    vsiArr.Add(vsi); }

    т.е. я заменил имена переменных типа  ViewSaveInfo (MyClass в первом примере) на имена констант enum-а, получить которые в виде строки несложно. А в массиве пусть безымянные объекты лежат :)

    Всем огромное спасибо за участие!


    • Изменено SvarogichRed 6 февраля 2013 г. 11:46
    6 февраля 2013 г. 11:44
  • Можно извратиться следующим образом:

    using System;
    using System.Linq.Expressions;
    
    namespace ConApp
    {
        public class MyClass { }
    
        public class Program
        {
            static string GetName<T>(Expression<Func<T>> expr)
            {
                var member = ((MemberExpression)expr.Body).Member;
                return member.Name;
            }
    
            static void Main(string[] args)
            {
                MyClass Var1 = new MyClass();
                MyClass Var2 = new MyClass();
                MyClass Var3 = new MyClass();
    
                MyClass[] mcArr = { Var1, Var2, Var3 };
    
                foreach (MyClass mc in mcArr)
                    Console.WriteLine(GetName(() => mc));
    
                Expression<Func<MyClass>>[] exprArr = { () => Var1, () => Var2, () => Var3 };
    
                foreach (var expr in exprArr)
                    Console.WriteLine(((MemberExpression)expr.Body).Member.Name);
            }
        }
    }


    В данном примере в первом цикле будут выводиться имена именно той переменной, что поступает на вход метода GetName, а именно: mc.

    Во втором случае я заношу в массив выражения (лямбды), таким образом сохраняются имена изначальных переменных, и именно они будут выведены в дальнейшем: Var1, Var2, Var3.

    Оно?

    P.S. при необходимости использовать в дальнейшем выражения из exprArr, можно компилировать их методом Compile().

    ----

    Пока писал сообщение, проблема решена автором. Но что-то решение не соответствует поставленному вопросу.

    • Изменено Petalvik 6 февраля 2013 г. 12:19
    • Помечено в качестве ответа SvarogichRed 7 февраля 2013 г. 3:19
    6 февраля 2013 г. 12:16
  • Таки да, оно!

    Вот спасибо, теперь знать буду.

    Конечно, моё решение - не решение, а "объезд" проблемы. Благодарю!

    7 февраля 2013 г. 3:25