Получение переменных из разных блоков кода C#
Могу ли я каким-то образом достучаться из одного блока кода до другого блока кода и получить от туда значение переменной (а может даже и саму переменную)? Я попытался с помощью рефлексии, но дальше не смог, не могу понять, как получить значения этих переменных
class Program
{
static void Main(string[] args)
{
var type = typeof(Program);
var method = type.GetMethod("M");
var body = method.GetMethodBody();
var variables = body.LocalVariables; //что дальше?
}
public void M()
{
int a = 5;
string b = "asdf";
}
}
Ответы (1 шт):
Берем ваш метод
public void M()
{
int a = 5;
string b = "asdf";
}
Компилируем, получаем ассемблер
Program.M()
L0000: ret
Компилятор просто взял и выкинул эти переменные из кода за ненадобностью, и правильно сделал. Приехали, на этом расследование завершено.
Окей, ради справедливости, давайте посмотрим на неоптимизированный Debug код.
Program.M()
L0000: push rbp
L0001: sub rsp, 0x30
L0005: lea rbp, [rsp+0x30]
L000a: xor eax, eax
L000c: mov [rbp-4], eax ; int a = 0;
L000f: mov [rbp-0x10], rax ; string b = null;
L0013: mov [rbp+0x10], rcx
L0017: cmp dword ptr [0x7ffcbd09c2f0], 0 ; стек переполнен?
L001e: je short L0025 ; если да
L0020: call 0x00007ffd109ec500 ; throw new StackOverflowException();
L0025: nop
L0026: mov dword ptr [rbp-4], 5 ; a = 5;
L002d: mov rax, 0x20db06e28c8 ; константа, адрес адреса "asdf"
L0037: mov rax, [rax] ; получить адрес "asdf"
L003a: mov [rbp-0x10], rax ; b = "asdf";
L003e: nop
L003f: add rsp, 0x30
L0043: pop rbp
L0044: ret
То есть если собирать Debug сборку, то значения переменных можно будет получить. Точнее есть такая теоретическая возможность.
Само собой константы типа 0x20db06e28c8 определяются во время JIT компиляции, как итог достать значение в рантайме можно, но очень нелегко. Еще следует учитывать, что JIT часть методов вообще не компилирует до тех пор, пока они не понадобятся. Например, зачем ему компилировать весь .NET в память, если вы 99% методов из него не используете? Логично же, что не стоит этого делать.
Что касается имен переменных, их нет даже в IL коде, то есть они существуют только в C# и при сборке удаляются.