Подтвердить что ты не робот

Получить имена параметров, переданных методу С#

void MyMethod(string something, params object[] parameters)
    {
      foreach (object parameter in parameters)
      {
        // Get the name of each passed parameter
      }
    }

Например, если я вызываю метод следующим образом, я хочу получить имена "myFirstParam" и "anotherParam".

string myFirstParam = "some kind of text";
string anotherParam = 42;
MyMethod("test", myFirstParam, anotherParam);

Возможно, размышление - это ответ? Возможно, это просто невозможно? Я знаю о существовании этого вопроса, но это решение не будет работать здесь.

(Пожалуйста, не отвечайте "Это не очень хорошая идея". Это не мой вопрос.)

4b9b3361

Ответ 1

Это абсолютно невозможно.

Вот лишь несколько случаев, когда это даже не имеет смысла:

MyMethod("abc", new object[5]);
MyMethod("abc", "def");
MyMethod("abc", var1 + var2);
MyMethod("abc", SomeMethod());
MyMethod("abc", b ? a : c);
MyMethod("abc", new object()); 
MyMethod("abc", null);

Фактически, локальные имена переменных даже не компилируются в сборку.

Ответ 2

В дополнение к SLaks ответ - имена переменных вообще не доступны во время выполнения. Переменные представляются слотами стека и адресуются индексом. Таким образом, вы не можете получить эту информацию даже для приведенного вами примера, не говоря уже обо всех этих примерах. Отражение здесь не помогает. Ничего нет.

Ответ 3

Это невозможно, и мне интересно, зачем вам это нужно.

Ответ 4

Как насчет этого?

void MyMethod(string something, object parameters)
{
RouteValueDictionary dic = HtmlHelper.AnonymousObjectToHtmlAttributes(options);
}

MyMethod("test", new { @myFirstParam=""some kind of text", anotherParam=42);

Это уже реализовано в System.Web.MVC.Html InputExtension.

Я был вдохновлен и использовал эту технику в своем коде. Он очень гибкий.

Не беспокойтесь о "Html" именовании в вспомогательных методах. Нет ничего общего с атрибутами html или html внутри вспомогательного метода.

Он просто преобразует именованные анонимные аргументы в RouteValueDictionary, специальный словарь с интерфейсом IDictionary<string,object>, где ключ содержит имя аргумента, а объект - значение аргумента.

Ответ 5

Использование отражения и пример @Martin тестирования нулевого аргумента:

using System.Reflection;

public SomeMethod(ClassA a, ClassB b, ClassC c)
{
    CheckNullParams(MethodBase.GetCurrentMethod(), a, b, c);
    // do something here
}

доступ к именам параметров:

public void CheckNullParams(MethodBase method, params object[] args)
{
    for (var i=0; i < args.Count(); i++)
    {
        if (args[i] == null)
        {
            throw new ArgumentNullException(method.GetParameters()[i].Name);
        }
    }
}

Это работает с конструкторами и общедоступными методами, но я не тестировал их вне модульных тестов в VS, поэтому, возможно, есть некоторые проблемы JIT во время выполнения (чтение статей, упомянутых выше).

EDIT: только что заметил, это по сути то же самое, что связанный ответ.

Ответ 6

Я ПОДНИМАЮ ЭТОТ ВОПРОС ОТ МЕРТВОГО!

Обратите внимание на новый оператор name # (#) С# 6.0. Это позволяет делать то, что вы хотите, и на самом деле это не всегда плохая идея.

Хорошим вариантом использования является исключение Argument, или INotifyPropertyChanged. (Особенно, когда вы получаете наследование в миксе)

Пример:

interface IFooBar
{
    void Foo(object bar);
}

public class FooBar : IFooBar
{


    public void Foo(object bar)
    {
        if(bar == null)
        {
            //Old and Busted
            //throw new ArgumentException("bar");

            //The new HOTNESS
            throw new ArgumentException(nameof(bar)); // nameof(bar) returns "bar"

        }

        //....
    }

}

Теперь, если вы переименовали параметр "bar" в методе "Foo" в интерфейсе IFooBar, ваши аргументы будут соответствующим образом обновляться (запрещает вам забывать изменить строку "bar" )

Довольно аккуратно!