Я просматривал исходное дерево .NET Core сегодня и перебегал этот шаблон в System.Collections.Immutable.ImmutableArray<T>:
T IList<T>.this[int index]
{
get
{
var self = this;
self.ThrowInvalidOperationIfNotInitialized();
return self[index];
}
set { throw new NotSupportedException(); }
}
Этот шаблон (сохранение this в локальной переменной), как представляется, последовательно применяется в этом файле всякий раз, когда this в противном случае будет ссылаться несколько раз в том же методе, но не в том случае, когда он ссылается только один раз. Поэтому я начал думать о том, какие относительные преимущества могут быть сделаны таким образом; мне кажется, что преимущество, скорее всего, связано с производительностью, поэтому я пошел по этому пути немного дальше... может быть, я забываю что-то еще.
CIL, который испускается для "store this в локальном" шаблоне, кажется, выглядит примерно как ldarg.0, затем ldobj UnderlyingType, затем stloc.0, чтобы более поздние ссылки исходили из ldloc.0 вместо голого ldarg.0, как это было бы просто использовать this несколько раз.
Возможно, ldarg.0 значительно медленнее, чем ldloc.0, но недостаточно для перевода С# -to-CIL или JITter, чтобы искать возможности для оптимизации этого для нас, так что имеет смысл писать это странный образ в коде С# в любое время, когда мы в противном случае испустили бы две инструкции ldarg.0 в методе экземпляра структуры?
Обновление: или, вы знаете, я мог бы взглянуть на комментарии в верхней части этого файла, которые объяснить, что именно происходит...