Где узнать о волшебных именах отладчика VS


110

Если вы когда-либо использовали Reflector, вы, вероятно, заметили, что компилятор C # генерирует типы, методы, поля и локальные переменные, которые заслуживают «специального» отображения отладчиком. Например, локальные переменные, начинающиеся с «CS $», пользователю не отображаются. Существуют и другие специальные соглашения об именах для типов закрытия анонимных методов, полей поддержки автоматических свойств и так далее.

Мой вопрос: где узнать об этих соглашениях об именах? Кто-нибудь знает о какой-то документации?

Моя цель - заставить PostSharp 2.0 использовать те же соглашения.

Ответы:


209

Это недокументированные детали реализации компилятора, которые могут быть изменены в любое время. (ОБНОВЛЕНИЕ: GeneratedNames.cs текущие подробности см. В источниках C #; приведенное ниже описание несколько устарело.)

Однако, поскольку я хороший парень, вот некоторые из этих деталей:

Если у вас есть неиспользуемая локальная переменная, которую оптимизатор удаляет, мы все равно отправляем отладочную информацию для нее в PDB. Мы прикрепили суффикс __Deleted$к таким переменным, чтобы отладчик знал, что они были в исходном коде, но не представлены в двоичном коде.

Слоты временных переменных, выделенные компилятором, получают имена с шаблоном CS $ X $ Y, где X - это «временный тип», а Y - количество выделенных на данный момент временных файлов. Временные виды:

0 --> short lived temporaries
1 --> return value temporaries
2 --> temporaries generated for lock statements
3 --> temporaries generated for using statements
4 --> durable temporaries
5 --> the result of get enumerator in a foreach
6 --> the array storage in a foreach
7 --> the array index storage in a foreach.  

Временные типы между 8 и 264 являются дополнительными хранилищами индексов для многомерных массивов.

Временные типы выше 264 используются для временных, включающих фиксированный оператор, фиксирующий строку.

Специальные имена, сгенерированные компилятором, генерируются для:

1 --> the iterator state ("state")
2 --> the value of current in an iterator ("current")
3 --> a saved parameter in an iterator
4 --> a hoisted 'this' in an iterator ("this")
5 --> a hoisted local in an iterator
6 --> the hoisted locals from an outer scope
7 --> a hoisted wrapped value ("wrap")
8 --> the closure class instance ("locals")
9 --> the cached delegate instance ("CachedAnonymousMethodDelegate")
a --> the iterator instance ("iterator")
b --> an anonymous method
c --> anonymous method closure class ("DisplayClass")
d --> iterator class
e --> fixed buffer struct ("FixedBuffer")
f --> anonymous type ("AnonymousType")
g --> initializer local ("initLocal")
h --> query expression temporary ("TransparentIdentifier")
i --> anonymous type field ("Field")
j --> anonymous type type parameter ("TPar")
k --> auto prop field ("BackingField")
l --> iterator thread id
m --> iterator finally ("Finally")
n --> fabricated method ("FabricatedMethod")
o --> dynamic container class ("SiteContainer")
p --> dynamic call site ("Site")
q --> dynamic delegate ("SiteDelegate")
r --> com ref call local ("ComRefCallLocal")
s --> lock taken local ("LockTaken")

Шаблон для генерации магических имен: P<N>C__SIгде:

  • P - это CS $ для кэшированных делегатов и экземпляров класса отображения, в противном случае - пусто.
  • N - исходное имя, связанное с вещью, если есть
  • C - это символы с 1 по s, перечисленные выше
  • S - это описательный суффикс («текущий», «состояние» и т. Д.), Так что вам не нужно запоминать приведенную выше таблицу при чтении метаданных.
  • I - необязательный уникальный номер

2
Спасибо! Я посмотрю, смогу ли я заставить классы закрытия PostSharp вести себя так же хорошо, как то, что генерирует компилятор C #!
— Gael Fraiteur

7
@SLaks: противоположность недолговечному временному. Долговечные временные переменные по сути являются локальными переменными без имен; у них есть определенное место в стеке, которое живет в течение всего времени существования кадра стека. Краткосрочные временные файлы просто помещаются в стек, когда их хранилище необходимо, и затем удаляются, когда оно больше не требуется. Долговечные временные конструкции намного легче отлаживать, но они могут значительно продлить срок службы временных файлов. Мы создаем долговечные временные файлы, когда оптимизация отключена.
— Эрик Липперт,

У меня есть концепция, аналогичная закрытым классам, но вместо того, чтобы поднять параметры как поля, я использую их как локальные переменные. Это очень хорошо работает для параметров, но как сообщить отладчику, что this - это не ldarg.0, а локальная переменная с индексом 4? Есть ли какое-нибудь волшебное имя?
— Гаэль Фрайтер,

23
@Eric - не могли бы вы обновить этот ответ именами, сгенерированными C # 5.0 (async / await)? Я видел несколько новых приставок :)
— Gael Fraiteur 08
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.