Давайте рассмотрим простой пример и код IL, который он генерирует (любезно предоставлено LinqPad)
void Main()
{
Bar();
Baz();
}
bool Bar()
{
return true;
}
void Baz()
{
Console.WriteLine("placeholder");
}
Это создает следующий IL:
IL_0000: ldarg.0
IL_0001: call UserQuery.Bar
IL_0006: pop //remove current value from evaluation stack
IL_0007: ldarg.0
IL_0008: call UserQuery.Baz
Bar:
IL_0000: ldc.i4.1
IL_0001: ret
Baz:
IL_0000: ldstr "placeholder"
IL_0005: call System.Console.WriteLine
IL_000A: ret
Вы видите Bar
вызывается, а затем всплывает, чтобы удалить логическое возвращаемое значение из стека оценки - это ни к чему не приведет.Мне пришлось обновить пример, чтобы включить еще один вызов метода в Baz()
, иначе всплывающее окно не будет отправлено, поскольку программа заканчивается.
Теперь давайте рассмотрим случай, когда мы фактически используем возвращаемое значение:
void Main()
{
bool foo = Bar();
Console.WriteLine(foo);
}
bool Bar()
{
return true;
}
Это приводит к следующему IL:
IL_0000: ldarg.0
IL_0001: call UserQuery.Bar
IL_0006: stloc.0 //pops current value from evaluation stack, stores in local var
IL_0007: ldloc.0
IL_0008: call System.Console.WriteLine
Bar:
IL_0000: ldc.i4.1
IL_0001: ret
Игнорировать часть System.Console.WriteLine
, которая является всем после и включая IL_007
- просто пришлось добавить ее, чтобы компилятор не оптимизировал прочьиспользование переменной.Вы видите, что результат вызова метода Bar
извлекается из стека оценки и сохраняется в локальной переменной foo
.В этом разница - либо pop
, который захватывает и отбрасывает возвращаемое значение, либо stloc.0
для присвоения результата переменной.
Так что если вам не нужны результаты вызова метода, выследует просто игнорировать результат.Даже если вы присваиваете результат переменной, и эта переменная никогда не используется, компилятор может полностью оптимизировать переменную и присвоение - по крайней мере, в режиме выпуска (в режиме отладки большинство оптимизаций отключены для улучшения вашего опыта отладки).