Skip to content

Instantly share code, notes, and snippets.

IOptions и Configure

В ASP.NET CORE Configure(extension) над IServiceCollection ///

@eterekhin
eterekhin / Сборщик мусора.md
Last active August 15, 2024 16:17
Сборщик мусора

Сборщик мусора написан в .net framework/core runtime пакетах Рихтер описывает его работу в .net framework. Создание объекта ссылочного типа алгоритмически можно описать так:

  • Подсчитать сколько необходимо выделить памяти под поля объекта(все поля включая и поля базового класса)
  • Подсчитать сколько необходимо выделить памяти на системные поля. Это указатель на объект тип и индекс блока синхронизации.
  • Проверить достаточно ли места в куче, если да, то обнулить байты начиная с NextObjPtr и создать объект, передав NextObjPtr в конструктор (как this). В конструкторе происходит инициализация всех полей объекта(для этого и передается NextObjPtr как this) и оператор new возвращает ссылку на новый объект. Перед возвратом NextObjPtr сдвигается и теперь указывает на первое свободное место после только что созданного объекта.

Сам этот процесс довольно прост и заключается в простом сдвиге указателя, (пока мы не рассматривали вариант, если в шаге 3 памяти не хватило). Зная такой алгоритм выделения памяти, можно сделат

Рихтер описывает то, как можно делать обработку в .net framework, но мы сейчас в .net core, я сейчас кратко опишу как происходит обработка контрактов в .net framework: Контракты бывают трех видов:

  • Предусловия - проверяются до начала работы метода
  • Постусловия - проверяются при окончании работы метода
  • Инварианты - проверяются после завешения любого метода в коде Как можно уже понять по определению инвариантов - контракты отрабатывают, переписывая код. В данном случае Рихтер пишет про IL код. Утилита для этого поставляется отдельно - CCRewrite.ext, после того, как в VS поставить флажок Perform Runtime Contract Checking, VS станет автоматически вызывать эту утилиту после компиляции сборки. Пример контракта:
    public class SalaryCalculator

У .net core существует пакет .net core sdk и .net core runtime
Первый нужен для того, чтобы компилировать C# код в IL, также там описана работа GC
Второй это C# реализация базовых классов, например коллекций и массивов
Задача SDK транслировать в IL код, который напишет программист, в том числе и код .net core runtime и выполнять этот код (GC, jit)

Как определить версии .net core sdk и .net core runtime используемые в текущем проекте

Поскольку в .net core работает принцип backward compatibility, то есть любая версия sdk больше указанной в TargetFramework подойдет(ее можно поменять в любой момент), но в таком случае скорость билда и jitting'a методов может измениться Версия .net core runtime выбирается как первая большая указанной в TargetFramework проекта
Например, если указанная версия netcoreapp2.1, то будет использоваться .net runtime version >= 2.1

В c# стандартные итераторы наследуюется от класса Iterator - суть которого контролировать, что все циклы foreach получат разные экземпляры итераторов если будут вызывать GetEnumerator из разных потоков. Для начала нужно вспомнить во что разворачивается foreach в C#

В цикле foreach используется утиная типизация, т.е:

class DuckEnumerator : IDisposable
    {
        public int Current { get; }

 public bool MoveNext()

В c# базовый класс для Exception'ов - Exception. В C# нельзя выбросить исключение другого типа. При возникновении исключения CLR начинает подниматься по стеку вверх и искать подходящий обработчик(блок catch), при этом вызывая все блоки finally, использует pattern maching для определения первого подходящео блока catch и вызывает его записывая трассировку стека от места возникновения исключения до места обработки, далее вам нужно выполнить код, который будет обрабатывать исключения и (возможно) выбрасывать его снова, в случае повторного выброса важно знать, что при таком выбросе трассировка будет сохранена(то же самое исключение будет возбуждено повторно):

А при таком - нет(на самом деле потеряется еще и TargetSite, будет возбуждено новое исключение):

Типам значения нельзя присвоить null, только default(type) - который null не является, поэтому возникла проблема как отличить отсутсвие значения value type от дефолтного значения, так и были созданы nullable типы: Nullable - структура

Немного о ThreadPool'e

  1. ThreadPool стартует задачи по очереди, поэтому возможна ситуация, когда задачи выполнятся друг за другом несмотря на то, что были запланированы в ThreadPool, смотрим:
 public static void ThreadPoolTest()
        {
            Console.WriteLine("ThreadPoolTest " + Thread.CurrentThread.ManagedThregadId);
        }

        public static void ThreadPoolTest1()
        {

Все атрибуты в .net должны наследоваться от класса System.Attribute. При этом создавая атрибут можно задать ему несколько свойств(используя атрибут AttributeUsageAttribute(у него есть такой же атрибут, кстати))

По умолчанию любой атрибут можно вешать на что угодно и использовать сколько угодно раз, и у наследников он тоже будет использоваться
Я думаю, что самая идея атрибутов которые можно вешать а потом рефлексивно получать значение очевдина,интереснее как это устроено внутри
Атрибуты можно вешать на классы, методы, аргументы методов,возвращаемое методом значение, свойства, поля, события, геттеры, сеттеры, конструктор, структуры..

Делегаты это обертка над функцией, которая принимает указатель на саму функции и контекст, если в коде создать делегат вида:

    public delegate int TestDelegate(int a, int b);

Его объявление в IL будет такое:

class public sealed auto ansi
  Resolvers.Tests.Delegates.TestDelegate
    extends [System.Runtime]System.MulticastDelegate