Как декомпилятор может распознать скомпилированную константу?

Я использую ILSpy для декомпиляции сборок .Net и просмотра кода. Просматривая код System.Windows.Vector.AngleBetween(Vector, Vector) в WindowsBase.dll, я наткнулся на нечто странное.

Это полный код функции:

public static double AngleBetween(Vector vector1, Vector vector2)
{
    double y = vector1._x * vector2._y - vector2._x * vector1._y;
    double x = vector1._x * vector2._x + vector1._y * vector2._y;
    return Math.Atan2(y, x) * (180.0 / Math.PI);
}

Очевидно, ILSpy смог распознать Math.PI, что является константой.

Вот что Документы Майкрософт говорит о константах в C#:

In fact, when the compiler encounters a constant identifier in C# source code, it substitutes the literal value directly into the intermediate language (IL) code that it produces.

Исходя из этого, то, что сделал ILSpy, кажется невозможным.

Примечание. Это поведение присутствует, даже если «Использовать имена переменных из символов отладки, если они доступны» и «Показывать информацию из символов отладки, если они доступны». параметры не отмечены в настройках.

Возможно, ILSpy просто знает значение общих констант, таких как Math.PI, когда видит их.

Blorgbeard 10.04.2019 20:31
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
1
350
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Быстрый тест в LINQPad показывает некоторые различия в сгенерированном коде IL (значение константы PI скопировано из здесь).

Источник:

void Main()
{
    double a = Math.PI;
    double b = 3.14159265358979;
}

ИЛ:

IL_0000:  nop         
IL_0001:  ldc.r8      18 2D 44 54 FB 21 09 40 
IL_000A:  stloc.0     // a
IL_000B:  ldc.r8      11 2D 44 54 FB 21 09 40 
IL_0014:  stloc.1     // b
IL_0015:  ret   

Кажется, что в коде IL, сгенерированном между константными и литеральными значениями, есть тонкая разница, но я пока не уверен, что именно это означает.


Приведенные выше значения из документация MSDN кажутся противоречащими информации из Справочный источник .NET (см. комментарии). При скорректированном коде из исходников IL идентичен.

Источник:

void Main()
{
    var a = Math.PI;
    var b = 3.14159265358979323846;
}

ИЛ:

IL_0000:  nop         
IL_0001:  ldc.r8      18 2D 44 54 FB 21 09 40 
IL_000A:  stloc.0     // a
IL_000B:  ldc.r8      18 2D 44 54 FB 21 09 40 
IL_0014:  stloc.1     // b
IL_0015:  ret   

Кроме того, похоже, что существует открытый вопрос для устранения несоответствия документации/исходного кода.

Math.PI определенно является константой, это объявление: public const double PI = 3.1415926535897931;
AstroRP 10.04.2019 20:32

Я просто обращался к документации MSDN из docs.microsoft.com/en-us/dotnet/api/…, в которой это указано как поле.

Bradley Uffner 10.04.2019 20:33

Значение, которое вы даете, также отличается от значения в связанной документации.

Bradley Uffner 10.04.2019 20:33

Согласно Справочный источник C#, вы правы. он объявлен как константа. Я скорректирую свой ответ.

Bradley Uffner 10.04.2019 20:36
Ответ принят как подходящий

Как вы можете видеть в этом ILSpy проблема и соответствующем пул реквест, это было специально реализовано (жестко закодировано) для известных значений, таких как Math.PI.

Из проблемы GitHub:

I suppose to calculate pi coefficient by following way: c = Math.PI / constant. If we getting "good" value (equal exactly to 1.0, 2.0, 0.5, 1/180 and so on), we simply replacing it with symbolic expression (Math.PI, Math.PI * 2, Math.PI / 2, Math.PI / 180 and so on).

Как тогда ILSpy может распознавать малоизвестные константы?

Dmytro Mukalov 10.04.2019 20:46

У вас есть пример неизвестной константы, которую он распознает?

Bradley Uffner 10.04.2019 20:50

@DmytroMukalov Вероятно, он может распознавать малоизвестные константы из символов отладки (файлы PDB), но я не проверял это.

Ghost4Man 10.04.2019 20:51

@DmytroMukalov Я только что проверил, и он не распознал Math.PI * 254.543, даже с включенным «использовать символы отладки»

AstroRP 10.04.2019 20:54

Другие вопросы по теме