Я просматривал исходное дерево .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
в методе экземпляра структуры?
Обновление: или, вы знаете, я мог бы взглянуть на комментарии в верхней части этого файла, которые объяснить, что именно происходит...