Где узнать о волшебных именах отладчика 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