Почему частные константы хранятся в сборках .NET?

Константы, на которые ссылается код, заменяются их фактическими значениями при компиляции в IL.

Поскольку на общедоступные константы можно ссылаться в коде за пределами конкретной сборки, имеет смысл хранить их в метаданных сборки.

Но почему там хранятся приватные константы? Нет ссылок на эти константы в IL кода в сборке, которая их определила, и они не доступны для ссылок за пределами сборки.

Итак, что нужно для доступа к этим значениям после компиляции кода?

Мне кажется, что все константы в сборках должны быть публичными, а приватные константы должны быть функцией уровня языка, которая просто заставляет компилятор выдавать литеральные значения.


person user2465452    schedule 07.11.2014    source источник
comment
Из-за BindingFlags.NonPublic. Возможность тыкать в интимные места чертовски удобна, когда вы находитесь в затруднительном положении, а программист не берет трубку, чтобы помочь вам.   -  person Hans Passant    schedule 08.11.2014
comment
Но какая польза от доступа к этой частной константе? Ни один IL не ссылается на эту константу. Все, что говорит вам о том, что кто-то решил использовать константу вместо того, чтобы где-то жестко запрограммировать значение.   -  person user2465452    schedule 08.11.2014
comment
Ну, конечно, IL ссылается на эту константу. Он встроен в IL. Если вы никогда не найдете этому применение, значит, жизнь удалась.   -  person Hans Passant    schedule 08.11.2014
comment
Я имею в виду, что в IL нет разницы между кодом, использующим константу, и кодом, использующим литерал. Другими словами, объявление (в C#) private const string MYCONST = "Hello World" и последующее выполнение Console.WriteLine(MYCONST) приводит к тому же IL, что и выполнение Console.WriteLine("Hello World").   -  person user2465452    schedule 08.11.2014


Ответы (1)


Компилятор C# может оптимизировать все виды личных вещей. Не только константы. Он может удалить неиспользуемые члены, классы, код. Это может убрать частные имена. Он может удалить частные свойства и заменить их методами. и Т. Д.

Доступ к рефлексии и инструменты перезаписи IL приходят на ум как важные варианты использования для личных вещей. Кроме того, отладка упрощается, когда большая часть метаданных все еще присутствует. Например, вы можете использовать Edit&Continue, чтобы использовать ранее неиспользованные элементы. Вы можете вызывать статически неиспользуемые элементы с помощью Immediate Window.

Возможно, есть последствия и для символов PDB, хотя сейчас я не могу об этом думать.

Обратите внимание, что сборки .NET содержат множество метаданных, которые только полезны для доступа к рефлексии. Атрибуты не имеют никаких последствий во время выполнения, кроме возможности проверки. Сборки должны быть насыщенными и информативными.

Можно возразить, что хранить константы особенно бесполезно, потому что они всегда статически не используются. Это, однако, не означает, что для них нет использования отражения. Они также могут помочь с декомпиляцией кода. Умный декомпилятор мог бы заметить, что некий литерал идентичен константе, объявленной рядом. Кроме того, зачем делать исключение для констант, чтобы оптимизировать их? В типичных программах очень мало констант. Даже если предположить, что их лучше убрать, вложения вряд ли окупятся. Лучше разрабатывать полезные функции языка одновременно.

person usr    schedule 07.11.2014
comment
Отражение может сообщить вам, что использовалась константа, но эта константа не упоминается ни в одном коде IL. Компилятор уже оптимизирует константу, вставляя литералы везде, где на нее есть ссылки. Доступ к другим закрытым членам можно получить через отражение, поэтому имеет смысл хранить информацию о них в метаданных. Но все, что вы получаете от констант, — это знание того, что программист решил их использовать. Атрибуты являются общедоступными и предназначены для программного доступа, чтобы влиять на логику, даже если они не делают этого автоматически. - person user2465452; 08.11.2014
comment
Предположение, что литералы с совпадающими значениями относятся к одной и той же константе, слишком подвержено ошибкам. Например, если я объявлю константу private const int SCHEMAVERSION = 1, то декомпилятор сопоставит этот код var x = myarray[myarray.Length - 1] с этим var x = myarray[myarray.Length - SCHEMAVERSION]. А бывают случаи, когда я могу ссылаться на внешнюю общедоступную константу, даже если локальная константа имеет то же значение. Если бы они хотели поддерживать это, я бы подумал, что у них была бы поддержка инструкций IL для констант, а затем позволили бы джиттеру вводить литералы. - person user2465452; 12.11.2014
comment
Что касается дополнительных усилий, необходимых для их оптимизации, то на самом деле их нет. Если бы они сделали константы IL общедоступными, то языки просто добавили бы в метаданные общедоступные константы, определенные языком. Тяжелая работа заключается в замене всех ссылок на константы литералами, и это было предписано спецификацией. Мне просто кажется странным, что они предписывают что-то подобное, а затем не определяют константы как общедоступные. - person user2465452; 12.11.2014