Skip to content

Instantly share code, notes, and snippets.

Что делает компилятор, когда встречает вызов метода с params аргументами

Сначала он воспринимает это как обычный вызов метода и проверяет не определен ли в типе, на котором вызывается метод, метод с такой сигнатурой, если не находит его, то просматривает extension методы и только потом метод с атрибутом ParamArrayAttribute, перед тем как вызвать этот метод, компилятор также записывает в IL код создания и инициализации массива, который нужно передать в метод

На каком месте должны стоять params аргументы

На последнем месте среди всех аргументов метода

Где размещается созданный массив ?

Компилятор генерирует класс и IL код который инициализирует этот массив значениям переданными в метод Автосгенерированный класс: (Я не понимаю где в IL коде передаются сами значения, которыми нужно проинициализировать массив)

Во что компилятор преобразует инициализацию объектов

Если это инициализация класса , то в последовательный вызов сеттеров свойств, или изменение полей, например Если массива, то вызов RuntimeHelper.InitializeArray(как в случае аргументов params) Если списка то это метод Add, кстати инициализаторы можно объявлять только для типов, содержащих метод Add

Как можно инициализировать вложенные коллекции и как можно инициализировать коллекции-переменные

Вложенные коллекции инициализируются вот так:

Как представлен тип System.Tuple в C# (какие поля, методы имеет)

Он имеет свойства без setter'a соответсвующие элементам, переданным в него и такие же приватные поля, getter'ы свойств ссылаются на приватные поля,имеет конструктор принимающий все аргументы, он реализует интерфейсы IStructuralEquatable,IStructuralComparable и еще несколько, эти интерфейсы показывают, что объект сравнивается как структура, т.e два объекта типа равны если попарно равны их поля, вот реализации интерфейсов Equals и GetHashCode интерфейса IStructuralEquatable, реализация Equals и GetHashCode просто ссылается на эти методы, также реализован интерфейс IComparable, метод CompareTo которого, также ссылается на одноименный метод IStructuralEquatable. Также Tuple реализует интерфейс ITuple в котором определена длина Length и индексатор. Всего определено 8 различных generic типов от Tuplt до Tuple, самое интересное, что T8 должен быть тоже Tuple( а точнее реализовывать ITupleInternal, почему реализация именно така

Что делать если в другом языке определено несколько индексаторов принимающий одинаковые параметры, и нужно использовать его в C#

Есть атрибут DefaultMemberAttribute который, насколько я понимаю, задает индексатор по умолчанию

Как компилятор оптимизирует вызов свойств

Jit компилятор вставляет код геттера или сеттера в вызывающий код, это называется инлайном метода, inline метода невозможен в debug'e, потому что усложняет его

Почему все сообщения от обработчика событий должны наследоваться от EventArgs

Это конвенция, на самом деле они могут и не наследоваться от этого класса, сам класс EventArgs просто заглушка, с readonly static полем Empty

Почему первый аргумент метода-подписчика должен иметь тип object

Первый аргумент это sender - отправитель сообщения, может возникнуть ситуация, когда события могут отправляться из наследника и из базового класса и все-равно нужно будет делать приведение вверх, на самом деле это просто рекомендация, вы можете сделать sender и конткретным типом

Привести пример правильной реализации оповещения подписчиков о прошествии события

 public class Person
        {
            public event TestDelegate AddSalary;

Какой код генерируется компилятором для управления событиями

Псевдокод: Для публичного события не переопределившего add и remove генерируется такой код:

 private static event Func<int, int> Event;

 public void add_Event(Delegate d)
 {
    Func<int, int> newDelegate;
 Func @event;

Какие рекомендации дает Microsoft по поводу наименовании generic параметров

Название должно начинать на T(например T,TKey,TValue)

В чем выигрыш в производительности при использовании generic типов и object типов, в каком случае выигрыш более значительный, когда generic тип - тип значения или ссылочный?

Более значительный выигрыш при использовани generic алгоритмов со значимыми типами, потому что альтернатива - упаковка значимого типа в object, и распаковка при извлечении результата, в случае с ссылочными типами, упаковка и распаковка не нужны, нужно делать только приведение к object и обратно, при использовании generic - реализации не нужно делать ни упаковку, ни приведение

Использование generic типов с параметрами значимых типов дает выигрыш только по скорости выполнения?

Нет, большое количество упаковки/распаковки приводит к выделению больших объмов памяти в куче, следовательно к более интенсивной работе сборщика мусора

Что такое открытые и закрытые типы в C#

Открытые типы - типы не запо

В книге описывается x86 платформа, поэтому все упоминаемые размеры могут быть некорректны в x64. Насколько я понял книга использует  .net framework  из 2015 кода. Поэтому все нижеперечисленное может быть ложно в новых версиях фреймворка.

Когда мы создаем класс, на этапе его промежуточной компиляции в IL(при создании AppDomain) добавляется много метаинформации во внутренние структуры CLR. Например создается  VTABLE, статические члены сохраняются в специальном массиве статиков(где он лежит и заполняется ли при первом обращении к статическу полю?). Строится Interface Virtual Map(IVM), для диспетчеризации интерфейсных методов. Вся эта информация используется в дальнейшем для генерации asm кода из IL кода. Сейчас мы рассмотрим в какой asm код компилируются вызов обычного, статического, виртуального и интерфейсного методов.

За итоговую компиляцию в asm отвечает jit. jit компилирует все методы лениво, компиляция происходит при первом вызове метода. До момента компиляции вместо asm кода, по ссылке на метод лежит

В чем будет проблема, если я из Class2 обращусь к типу NestedDir1?(все namespace названы в соответсвие с папками в которых лежат)
В том, что компилятор не поймет что это обращение к namespace NestedDir1 , или к сущности NestedDir1, будет такая ошибка:
Это происходит из-за того, что название одной папки в иерархии такое же как и название класса, поэтому придется указать явный путь до класса:
Все дело в том, что у нас есть доступ к папкам(namespace'ам) на том же уровне:

Как происходит вызов метода интерфейса

В AppDomain'e есть таблица интерфейсов, в которой представлены все реализации всех интерфейсов домена, при вызове метода интерфейса, идет обращение к этой таблице, через эту таблицу интерфейсов можно получить обратную ссылку на подтаблицу в MT типа, через которую и вызвать метод, но это очень долгий путь, на самом деле его можно ускорить, [подробнее(https://gist.github.com/brager17/eb14ee2085eeb0813c58e69bc8ce5474)

Что такое выбор горячего пути при вызове метода интерфейса

Если происходит многократный вызов метода интерфейса то он перестает использовать глобальную таблицу интерфейсов и кеширует адрес MT типа, на котором вызывается метод, таким образом вызов происходит явно, [подробнее(https://gist.github.com/brager17/eb14ee2085eeb0813c58e69bc8ce5474)

В каких случаях происходит упаковка value type

Нужно сначала разобраться в определении: Упаковка - выделение места для структуры в куче и последующее ее копирование в кучу. При этом у упакованной структуры п