Как стать автором
Обновить

Комментарии 20

Сюда же в копилку можно добавить Enum.HasFlag, по тем же причинам.

HasFlag вообще расстроил. :(

При его вызове аж 2 явные команды упаковки, если мы работаем напрямую с экземпляром перечисления.

Код на C#:

enum Origin { None }

void Test(Origin origin) 
{     
  var eq = origin.HasFlag(Origin.None); 
}

IL:

.method private hidebysig instance void  
  Test(valuetype HasFlagTest.Program/Origin origin) cil managed
{
  // Code size       19 (0x13)
  .maxstack  8
  IL_0000:  ldarg.1
  IL_0001:  box        HasFlagTest.Program/Origin
  IL_0006:  ldc.i4.0
  IL_0007:  box        HasFlagTest.Program/Origin
  IL_000c:  call       instance bool [mscorlib]System.Enum::HasFlag(class [mscorlib]System.Enum)
  IL_0011:  pop
  IL_0012:  ret
}

Да, но он девиртуализирован в .NET Core и не аллоцирует ;-)

Действительно... Здорово же! :)

А дженерик им что мешало вместо костыля сделать, интересно?

Вы ассемблер смотрите, а не IL. Очевидное "неочевидно", может быть неочевидно.

Правда ваша.

Но в случае для .NET Framework, в принципе, достаточным оказалось посмотреть выделение памяти / сборку мусора.

Это да.
Просто привычка. https://sharplab.io/
Удобная штукенция.

По поводу Equals(object,object) - у нас уже есть фикс для этого в dotnet/runtime, но пока это еще не вмерженно. Там необходим escape analysis чтобы понять что бокшенный value type никуда не убегает и можно не боксить, либо эмулировать боксинг но на стеке.

А можно ссылочку на PR или иное место, где это реализовано? Интересно глянуть. :)

А будет какое-то отличие в поведении, если перечислениям в enum будет присвоено явное значение?

enum Colors {
  Red = 1,
  Green = 2,
  Blue = 3
  } 

Если мне не изменяет память - никаких отличий не должно быть. Значения у enum и так и так присвоены - только если вы их не указываете явно - они начинаются с 0 и увеличиваются с шагом в единицу. А так там просто будут другие числа, только и всего.

Да, Вы правы.

Единственное насторожило это низкий уровень входа в шарпы) если сравнить с питоном, то шарп имеет очень высокий уровень вхождения)

Тут уж мне сложно судить - на Питоне не писал, так что поверю на слово. :)

Если вы собрались писать оптимальный кол на шарпе, то неожиданный боксинг/анбоксинг это одно из первых мест куда надо смотреть. Чтобы упростить эту задачу, сто лет назад изобрели плагин для решарпера/райдера: https://plugins.jetbrains.com/plugin/9223-heap-allocations-viewer. Ну а решарпер/райдер это must have

Не слышал про такой, возьму на заметку на всякий.

Мы недавно занимались оптимизациями, как раз дописал статью на эту тему. Были разного рода оптимизации, в том числе в некоторых местах приходилось экономить на каждом временном объекте.

Собственно, насколько помню, с упаковкой проблемы были в одном месте - описанном в этой статье. Может быть повезло просто, конечно. А может и нет. :)

Спасибо за ссылку на плагин!

Про маст хэш - очень холиварно. На наших солюшенах он виснет и не даёт нормально работать (ссд, нвме).

Но то, что есть плагин - хорошо.

Просто поделюсь болью: в Unity (Mono) не спасает EqualityComparer.Default. Для enum используется EnumEqualityComparer<T>, который реализует Equals как

return JitHelpers.UnsafeEnumCast<T>(x) == JitHelpers.UnsafeEnumCast<T>(y)

а UnsafeEnumCast это

return Array.UnsafeMov<T, int>(val)

который

return (R) (object) instance

...

D:

Зарегистрируйтесь на Хабре, чтобы оставить комментарий