То, что название проекта такое есть, я заметил, спасибо. Там нет бенчмарка, проверяется один и тот же класс, написанный автором, только с разными параметрами. Бенчмарк по определению должен сравнивать производительность одного и того же метода, написанного по-разному. И исходя из текста статьи, я думал, что будет сравниваться как раз-таки с регулярнками.
Так и что вас в нём смущает? Или вы хотите сказать, что тут не очевидно, что var — это PerformanceCounterCategory?
Ну и, как я сказал, диагностики студии предлагают менять на var почти везде.
Видимо, у вас почти везде используются явные типы там, где они не нужны. Сути это не меняет совершенно.
А если вспомнить, что придуман он был для Linq, где как раз точный тип неочевиден (просто не очень важен)
Я понимаю, что вы вообще не про Linq, а про анонимные типы, но вы постулируете просто городские легенды. var — это вещь в себе, он был придуман не «для Linq», который прекрасно живёт без него и не только для анонимных типов. Впредь прошу для утверждений вроде «придуман он был для Linq» приводить ссылки на документацию.
Тут много правильных слов уже сказали о качестве кода, их я повторять не буду. Можно на пальцах объяснить, в чём проблема вашего кода: давайте допустим, что мы решили добавить формат «yyyy-MM-dd HH:mm:ss.fff». И вдруг вам теперь для одного изменения нужно переписывать вообще всё. Весь код гвоздями прибит к одному конкретному набору данных и не предполагает изменений вообще, не переписывая код.
я решил сразу отметать плохо зарекомендовавшие себя в плане эффективности практики типа регулярных выражений
Вот это интересно, но хочется хоть какого-то обоснования этому. В целом, задача — на регулярки; дальше вы пишите, что добавили в проект бенчмарки, но их в проекте нет. Забыли добавить?
Вместо var рекомендуется сразу указывать тип, с которым будете работать, чтобы соблюдалась «строгая типизация», например int number = 0 вместо var number = 0
C# — язык строгой типизации, и var — это просто alias явного типа. Там всё равно будет int. И нет, если тип очевиден, это просто лишние символы, так писать не рекомендуется.
Задумался о том, что меня смутило в главе об оптимизации Linq. Если запросы «сотни тысяч и даже миллионы раз», то они как минимум должны кэшироваться, а не проходить каждый раз заново. Но возможно, тут какой-то интересный кейс, где кэшировать невозможно. Хотелось бы подробностей.
Вообще не существует задачи «хранить данные», есть только задача «получать к данным доступ».
Во-первых, я не говорил, о том, что есть «задача хранить данные».
Во-вторых, иногда она на самом деле есть. Если мне нужен быстрый массив для текущих расчётов, то я скорее создам его через stackalloc, потому что мне нужно хранить такие данные на стеке. Пусть такая ситуация редка и возникает уже на этапе оптимизации, но она вполне реальна.
В-третьих, а как вы решаете задачу «получать к данным доступ»?
Для высокоуровневой логики совершенно фиолетово, где там и что лежит.
Так C# используется не только для высокоуровневой логики.
Эм. Во-первых, это в другом разделе, поэтому странно говорить о том, что там «потом», как будто «потом» менее важно. А во-вторых, я же не утверждал обратного. Но вот вы утверждали, что нужно забыть то, что есть в документации.
Кстати, по моей практике, нет. Про boxing/unboxing большинство что-то слышали и с разной степенью уверенности могут ответить, что в случае боксинга значение попадет в кучу.
Хм, интересно, конечно. Люди, которые слышали про боксинг, но не слышали о том, что value типы бывают внутри reference) Но не спорю, такое может быть.
Семантика типов-значений и типов-ссылок от этого не изменится.
Ну так да. Неважно, где там именно хранятся ссылочные типы. Важно, что их хранение отличается от value типов. Я о чём. Да, то, что там происходит в рантайме — дело прежде всего рантайма, это факт. Но райнтайм .NET и C# не независимы и при помощи упомянутых мной ключевых слов можно напрямую влиять на то, как будет аллоцирована память.
Хотя постойте… Зачем представлять? Уже есть Large Object Heap, и рантайм решает за нас, аллоцировать память в SOH или в LOH.
А ещё с .net 5 есть Pinned Object Heap, так что туда добавим, простите, POH. Но это всё — способы оптимизации кучи, уже действительно детали рантайма, и мы на них никак не можем повлиять напрямую. Поэтому:
но с точки зрения языка C# разницы между «small» reference type и «large» reference type нет
Да. Но разница между value type и reference type — есть)
Я могу вам точно сказать, что ref struct хранится в куче. Официально «кучевый тип»? )
Касательно обучающихся. В бытность преподавания программирования, я объяснял типы на примере мессенджера.
Допустим, я хочу отправить Васе и Оксане видос. Я могу взять где-то файл, отправить два раза его, при этом он будет долго и неприятно ползти по сети до них. А могу залить куда-нибудь на YouTube и отправить ссылку. Это быстро. Пожалуйста, ссылочный тип.
Затем, я хочу отправить им слово «Привет». Если бы у меня был только механизм ссылок, мне пришлось бы где-нибудь размещать слово, крафтить на него ссылку, и отправлять ссылку. Но намного быстрее (и адекватнее, доложу я вам) просто отправить само слово. Пожалуйста, тип-значение.
При этом слово «Привет» может быть и в видосе, но от этого оно (слово) не перестанет храниться по ссылке.
О, один из моих любимых холиваров. Постараюсь язвить поменьше, если что — заранее извиняюсь.
Спасибо за обзор, но забудьте уже, что [...]
Честное слово, 9 из 10 собеседуемых отвечают таким образом.
А как вы предлагаете им отвечать, если это написано на страничке описания типов C#?
Value types:
There's no separate heap allocation or garbage collection overhead for value-type variables.
Reference types:
When the object is created, the memory is allocated on the managed heap, and the variable holds only a reference to the location of the object.
Во-первых, сами типы не размещаются на стеке, речь в лучшем случае должна идти о _локальных переменных_ этих типов.
Позвольте мне также побыть занудой и заметить, что локальные переменные не размещаются на стеке, там размещаются _значения_ локальных переменных ;) Но всё-таки, «типы размещаются на стеке» — это удобное упрощение, как мне кажется.
Когда задаешь вопрос, а где тогда располагается значение поля типа int экземпляра класса, примерно треть утверждает, что на стеке, остальные догадываются, что видимо все-таки в куче, хоть оно и значимого типа.
Действительно, догадаться можно, но чтобы поставить собеседуемого в тупик лучше спрашивать про боксинг, и вот тогда процент догадывающихся резко упадёт.
Во-вторых, это деталь реализации рантайма, которая не имеет отношения к языку.
Если бы отношения не было, в языке не было бы, например, ключевых слов (либо они имели бы другое назначение) in, ref (в том числе ref struct), stackalloc.
А в третьих, если место аллокации локальных переменных было бы ключевым отличием, то и типы назывались бы кучевыми и стековыми. Но они почему-то называются ссылочными и значимыми. Может быть потому, что ключевое различие в семантике присваивания — либо копированием ссылки_, либо копированием _значения_?
То есть ref int — это ссылочный тип? stackalloc int[] — это значимый тип? А присваивание боксингом куда попадёт?
Всё-таки, на мой взгляд, то, как присваиваются значения — это важное, но всё-таки следствие того, где значения располагаются. Также, например, важным следствием является то, как идёт очистка памяти от значений.
А в чём кейс? Разделили одно целое (int) число на другое — получили 0, т.к. 0.5 целым никак не получится сделать. Следовательно 2.5 + 0 -> 2.5
И никаких подвохов
Для этого делают тестирование производительности. Для простых случаев вроде вашего такого не случится.Нет, у вас совершенно банальная задача для элементарных регулярок.
Есть пример, может быть? Голословно сложно что-либо обсуждать.
А кодеров, конечно, от компании.
PerformanceCounterCategory?Видимо, у вас почти везде используются явные типы там, где они не нужны. Сути это не меняет совершенно.Я понимаю, что вы вообще не про Linq, а про анонимные типы, но вы постулируете просто городские легенды. var — это вещь в себе, он был придуман не «для Linq», который прекрасно живёт без него и не только для анонимных типов. Впредь прошу для утверждений вроде «придуман он был для Linq» приводить ссылки на документацию.
Вот это интересно, но хочется хоть какого-то обоснования этому. В целом, задача — на регулярки; дальше вы пишите, что добавили в проект бенчмарки, но их в проекте нет. Забыли добавить?
Ну так они и не обязательны. Можно писать без всего этого.
Во-вторых, иногда она на самом деле есть. Если мне нужен быстрый массив для текущих расчётов, то я скорее создам его через
stackalloc, потому что мне нужно хранить такие данные на стеке. Пусть такая ситуация редка и возникает уже на этапе оптимизации, но она вполне реальна.В-третьих, а как вы решаете задачу «получать к данным доступ»?
Так C# используется не только для высокоуровневой логики.
Хм, интересно, конечно. Люди, которые слышали про боксинг, но не слышали о том, что value типы бывают внутри reference) Но не спорю, такое может быть.
Ну так да. Неважно, где там именно хранятся ссылочные типы. Важно, что их хранение отличается от value типов. Я о чём. Да, то, что там происходит в рантайме — дело прежде всего рантайма, это факт. Но райнтайм .NET и C# не независимы и при помощи упомянутых мной ключевых слов можно напрямую влиять на то, как будет аллоцирована память.
А ещё с .net 5 есть Pinned Object Heap, так что туда добавим, простите, POH. Но это всё — способы оптимизации кучи, уже действительно детали рантайма, и мы на них никак не можем повлиять напрямую. Поэтому:
Да. Но разница между value type и reference type — есть)
Касательно обучающихся. В бытность преподавания программирования, я объяснял типы на примере мессенджера.
Допустим, я хочу отправить Васе и Оксане видос. Я могу взять где-то файл, отправить два раза его, при этом он будет долго и неприятно ползти по сети до них. А могу залить куда-нибудь на YouTube и отправить ссылку. Это быстро. Пожалуйста, ссылочный тип.
Затем, я хочу отправить им слово «Привет». Если бы у меня был только механизм ссылок, мне пришлось бы где-нибудь размещать слово, крафтить на него ссылку, и отправлять ссылку. Но намного быстрее (и адекватнее, доложу я вам) просто отправить само слово. Пожалуйста, тип-значение.
При этом слово «Привет» может быть и в видосе, но от этого оно (слово) не перестанет храниться по ссылке.
А как вы предлагаете им отвечать, если это написано на страничке описания типов C#?
Value types:
Reference types:
Позвольте мне также побыть занудой и заметить, что локальные переменные не размещаются на стеке, там размещаются _значения_ локальных переменных ;) Но всё-таки, «типы размещаются на стеке» — это удобное упрощение, как мне кажется.
Действительно, догадаться можно, но чтобы поставить собеседуемого в тупик лучше спрашивать про боксинг, и вот тогда процент догадывающихся резко упадёт.
Если бы отношения не было, в языке не было бы, например, ключевых слов (либо они имели бы другое назначение)
in,ref(в том числеref struct),stackalloc.То есть ref int — это ссылочный тип? stackalloc int[] — это значимый тип? А присваивание боксингом куда попадёт?
Всё-таки, на мой взгляд, то, как присваиваются значения — это важное, но всё-таки следствие того, где значения располагаются. Также, например, важным следствием является то, как идёт очистка памяти от значений.
И никаких подвохов