Получить имя параметра с помощью функции

Главное

Пишу библиотеку для консольных приложений и там есть функция которая выводит информацию о переменной. Только в нём одна проблема. Функция в начале должна выводить имя получаемого параметра а выводит имя переменной в функции.


Подробнее

Library.cs

using System;

namespace Library
{
    public class Print
    {
        ...
        public static void Information(object variable)
        {
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine($"Name - {nameof(variable)}"); //Вот тут проблема
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine($"Type - {variable.GetType()}");
            Console.WriteLine($"Hash Code - {variable.GetHashCode()}");
            Console.WriteLine($"Value - {variable}");
        }
        ...
    }
}

Program.cs

using System;
using Library;

namespace Script
{
    class Program
    {
        static void Main(string[] args)
        {
            float interval = 1.2f;
            Print.Information(interval);
        }
    }
}

В итоге получаем

То есть мне надо было вместо Name - variable - Name - interval.
Собственно как это исправить?


Ответы (1 шт):

Автор решения: Exploding Kitten

Можно воспользоваться Expression Trees:

using System;
using System.Linq.Expressions;

class Test 
{
    public int z => 1;
}

class Program
{
    private static int private_field = 1;

    static void Main(string[] args)
    {
        int xxx = 1;
        // обычная переменная
        Test(() => xxx); // Выведет xxx

        // аргументы "внешнего" метода
        Test(() => args); // Выведет args

        // член класса
        Test(() => private_field); // Выведет private_field

        // более сложная конструкция
        Test(() => new Test().z); // Выведет z
    }

    public static void Test<T>(Expression<Func<T>> expression)
    {
        if (expression.Body is MemberExpression member)
        {
            Console.WriteLine($"Name: {member.Member.Name}"); // имя переменной
            Console.WriteLine($"Value: {expression.Compile()()}"); // значение
        }
        else
        {
            throw new NotSupportedException();
        }
    }
}

Но все равно мне такой код кажется странным (т.к. у вас достаточно простой случай, просто одна переменная, имя которой известно на этапе компиляции), я бы все же использовал дополнительный параметр, например: void Information(string name, object value), тогда можно было бы передавать его как Information(nameof(interval), inverval) или же это все обвернуть в class/struct, если таких значений несколько, то можно и словарь.

→ Ссылка