• Где находится статический класс в памяти?

    ayazer
    @ayazer
    Sr. Software Engineer
    , но таблицы методов создаются под каждый объект класса индивидуально.

    нет, вы что-то путаете. 1 таблица на каждый тип, нет смысла создавать копию под каждый объект. ну и теперь ответ на остальную часть вопроса становится очевиден - нет разницы между таблицей методов для статического/не статического класса - все лежит где-то в куче в AppDomain.

    upd:
    В какой памяти находится статический класс, в куче, по идее?
    конечно, только не в той которая SOH/LOH, а в той что упоминается у рихтера как "на самом деле куч больше чем 2, но остальное вам не нужно". А если еще точнее - в high frequency heap. Не знаю зачем это знание вам надо, но живите теперь с этим.

    Статический класс - это объект-тип, который содержит таблицу методов, но только статических и статического конструктора?

    мех, на самом деле так себе формулировка. лучше остановится на том, что в контексте c# - статический объект это специальный случай объекта, который может содержать только статические поля/методы.
    Ответ написан
    1 комментарий
  • Как происходит вызов сокрытого метода под капотом?

    ayazer
    @ayazer
    Sr. Software Engineer
    а в книгах этого и не должно быть. вы сейчас спрашиваете про детали реализации, которые даже рамках .нета могут отличатся (.нет это же не только c#). Обычно за такими знаниями нужно лезть конкретно в кишки компилятора/рантайма. Но помните что знание нескольких принципов заменяет знание многих нюансов, и обычно понимания "как оно обычно устроено" хватает с головой.

    и отвечая конкретно на этот вопрос - какой именно метод вызывать определяется в рантайме на основе информации в виртуальной таблице которая сотв. классу. И у рихтера точно есть упоминание об этом (что вызов виртуального метода несколько медленей т.к. приходится делать дополнительную проверку по виртуальной таблице чтоб понять что именно нужно вызывать).

    В целом это происходит +- так:
    1. для каждого класса создается виртуальная таблица а-ля [method_id address ...]

    Class1:
    0x001 0x0001 ...
    0x002 0x0100 ...
    ...

    Class2:
    0x002 0x0F00 ...
    ...

    2. когда вы делаете instanceOfMyClass.DoSomethingUsefull(...) CLR проверяет виртуальный таблицы (возможно пробегается по всей иерархии наследования, чтоб понять где точно лежит нужный метод) и дальше вызывает его передав в него адресс где в памяти лежит сам класс И список параметров с которыми вызывается метод.

    ^ могу ошибатся в нюансах, но принцип такой
    Ответ написан
    Комментировать
  • Куда записываются данные о том, что такая-то переменная является константой?

    ayazer
    @ayazer
    Sr. Software Engineer
    вы же уже спрашивали: Где в экземпляре примитивного ссылочного типа, например string, находится информация о том, что этот экземпляр — константа?

    когда код уже скомпилирован - это нигде не хранится т.к. у нас записаны просто значения.
    во время компиляции - оно хранится вот так https://github.com/dotnet/roslyn/blob/7a836c8e5a06...

    например для const decimal во время компиляции будет использоватся вот это https://github.com/dotnet/roslyn/blob/7a836c8e5a06...

    Но опять таки - это нужно только компилятору чтоб знать что с этими значениями делать. В результате значения констант будут подставлены по всем местам использования (о чем вы можете легко убедится декомпилировав код)
    Ответ написан
  • Как вызвать деструктор?

    ayazer
    @ayazer
    Sr. Software Engineer
    не нужно ручками вызывать деструктор, он будет вызван когда GC будет освобождать ресурсы.
    Ответ написан
    Комментировать
  • Какую базу данных выбрать для временных данных?

    ayazer
    @ayazer
    Sr. Software Engineer
    та любую TSDB можно брать. с тех что на слуху - influx/prometeus/Riak-ts.
    Ответ написан
    Комментировать
  • Не качается фото с сообщения юзера в телеграм боте?

    ayazer
    @ayazer
    Sr. Software Engineer
    ну для начала исправить на

    private static async Task DownloadFile(string fileId, string path)


    и использовать как
    await DownloadFile(message.Photo[message.Photo.Count() - 1].FileId, "photo" + id + ".jpg");
    Ответ написан
    5 комментариев
  • Отличия GET и POST запросов в контексте ASP.NET MVC 5?

    ayazer
    @ayazer
    Sr. Software Engineer
    к asp.netу отношения не имеет, это часть http стандарта (GET - https://tools.ietf.org/html/rfc2616#section-9.3, POST - https://tools.ietf.org/html/rfc2616#section-9.5)

    по применению - это вам скорее про REST читать. в целом - GET это получение информации, POST - добавление новой.
    Ответ написан
    Комментировать
  • Как отправить массив байтов по UDP в C#?

    ayazer
    @ayazer
    Sr. Software Engineer
    у вас дамп в 16ичной системе то. Либо указывайте тип исчисления при создании массива, либо переводите в 10чную

    byte smert = new byte[] { 0x02, 0x00, 0x00, 0x00, 0x45, 0x00, 0x05, 0xd4, .... , 0x63, 0x64}
    Ответ написан
    3 комментария
  • Где в экземпляре примитивного ссылочного типа, например string, находится информация о том, что этот экземпляр - константа?

    ayazer
    @ayazer
    Sr. Software Engineer
    если поле константа - все использования этого поля будут заменены на значение константы в момент компиляции.

    исходный пример:
    class Program
        {
            static void Main(string[] args)
            {
                const int i1 = 10;
                var k1 = i1 + Func(i1);
                Console.WriteLine(k1);
    
    
                var i2 = 10;
                var k2 = i2 + Func(i2);
                Console.WriteLine(k2);
            }
    
            private static int Func(int i)
            {
                return i * 2;
            }
        }


    результат декомпиляции:
    internal class Program
      {
        private static void Main(string[] args)
        {
          Console.WriteLine(10 + Program.Func(10));
          int i = 10;
          Console.WriteLine(i + Program.Func(i));
        }
    
        private static int Func(int i)
        {
          return i * 2;
        }
      }
    Ответ написан
    4 комментария
  • Как в куче показано или записано, что, например, класс В наследуется от класса А?

    ayazer
    @ayazer
    Sr. Software Engineer
    So, как в куче помечено, что класс B унаследован от класса А?

    это настолько нюанс, что вспомнить сложно даже если надо. когда вы создаете объект - в куче выделяется место под структуру данных. В ней записана метаинформация (гуглить по EEClass) и потом идет таблица с адресами методов. Вот вам куда-то в кишки EEClass залазить надо, в оф. документации точно было детальное описание.

    вот можно начать отсюда https://docs.microsoft.com/en-us/archive/msdn-maga...

    Почему это происходит?

    потому что-то конструктор класса А может инициализировать поля которые потом нужны конструктору класса B.
    Ответ написан
    4 комментария
  • Как работают передачи разных ссылочных типов в качестве параметра в метод и правильно ли я понял, как устроен массив в памяти?

    ayazer
    @ayazer
    Sr. Software Engineer
    ну скопировали бы код, есть же подсветка синтаксиса на тостере. Пытаться что-то разобрать на скриншотах - боль. Один на вид еще и пожат до состояния что сложно что-то разобрать. Ну а еще лучше - сформулировать конкретный вопросы, и задавать их отдельно. Сложно за один раз ответить на 5 скриншотов с кодом и рисунками.

    Но по тому что я заметил - вам в голове нужно уложить пару фактов. И тогда все станет на свои места.

    1) все есть object
    2) все value type (честно, впал в ступор пытаясь вспомнить корректный перевод) - тоже наследуются от object (точнее от ValueType, который уже наследуется от object). А на уровне компилятора есть проверка наследуется ли класс от ValueType, чтоб знать как с ним работать дальше (т.е. где хранить и как передавать)
    3) с одной стороны - строка тоже object, а с другой стороны - строка иммутабельна. потому любая попытка ее изменить будет на самом деле создавать измененную копию строки.
    Ответ написан
    Комментировать
  • Как вызвать метод, в засисимости от значения переменной?

    ayazer
    @ayazer
    Sr. Software Engineer
    судя по всему вы пытаетесь получить такое поведение. Но да, выглядит как не лучшее решение. Только я не понимаю откуда такая категоричность про использование switch

    public class Class1
        {
            private readonly Action _action;
    
            public Class1(string actionName)
            {
                switch (actionName)
                {
                    case "1":
                        _action = Action1;
                        break;
                    case "2":
                        _action = Action2;
                        break;
                    default:
                        throw new Exception($"Unexpected action name {actionName}");
                }
            }
    
            public void Act()
            {
                _action.Invoke();
            }
    
            private void Action1()
            {
                // ...
            }
    
            private void Action2()
            {
                // ...
            }
        }
    Ответ написан
    Комментировать
  • Как инвертированный индекс хранит несколько значений в одном поле?

    ayazer
    @ayazer
    Sr. Software Engineer
    С одной стороны - да, не нормализирована и вообще - классический антипаттерн проектирования, когда в одно поле пихают значения через запятую.

    С другой - надо посмотреть на предметную область и подумать - а дейстительно ли есть есть смысл в разделении? На вид конкретно в данном случае - майскл используется как key-value хранилище, которое быстро достает список документов и отдает его наружу. Дальше сервис уже сделает сплит по запятой и пойдет доставать документы куда-то с хранилища/пойдет куда-то в солр/еластик чтоб уточнить информацию по каждому конкретному документу. Т.е. в случае если нам всегда нужен весь список документов - мы имеем ситуацию когда от разделения мы только теряем (т.к. больше таблиц, больше джойнов, сложнее структура, больше цпу/рам тратится чтоб все достать/хуже кеш хит => мы можем выдержать меньшую нагрузку).

    Нужно четко различать где денормализация т.к. так нужно, а где - т.к. нехватка времени/знаний/желания. И да, этот пример скорее для демонстрации идеи. В реальном мире может оказаться что по ключу "key1" будет лежать строка в пару гигабайт, потому настолько наивный подход работать не будет.
    Ответ написан
    Комментировать
  • Название игр для изучения програмирования?

    ayazer
    @ayazer
    Sr. Software Engineer
    "вот компилятор, вот справочник, можешь написать свою змейку". Если не сработает - может и не надо?

    зы: а по теме - почти любая с игр от Zachtronics (https://store.steampowered.com/developer/zachtronics/) подойдет. SpaceChem/TIS-100/shenzen IO/opus magnum/exapunks/molek-syntez алгоритмическое мышление должны хорошо качать. Там иногда такие задачки бывают что вечером после работы слету и не решишь.
    Ответ написан
    1 комментарий
  • Какие есть достойные альтернативы жадному алгоритму (greedy)?

    ayazer
    @ayazer
    Sr. Software Engineer
    ну после всех выяснений выходит что у вас действительно задача про n рюкзаков. Тогда как уже заметили
    - это действительно np-полная задача со всеми вытекающими проблемами и подходами к решению. Ну и я уже писал что с использованием MIP солвера оно решается буквально в пару строчек (без использования - писать кода прийдется заметно больше). Вот тут https://python-mip.readthedocs.io/_/downloads/en/l... даже есть пример для решения рюкзака, его надо просто расширить с условием что рюкзаков много и нужно строгое совпадение.

    зы: может оказатся что данных сильно много и подход с использованием MIP "в лоб" будет работать сильно медленно. В таком случае уже можно будет думать и комбинировать разные подходы.

    зыы: питоновский код чисто для примера, обертки для cbc (https://github.com/coin-or/Cbc) есть уже наверно для всех языков где это может понадобится, потому менятся будет только синтаксис. под капотом там одни фиг будет плюсовая либа

    на вид должно выйти что-то такое

    from typing import List
    from mip import Model, minimize, xsum, BINARY
    
    
    def solve(input_values: List[int], target_values: List[int]):
    
        model = Model("m")
    
        bin_input_is_used_to_build_target = {}
    
        for index in range(0, len(input_values)):
            bin_input_is_used_to_build_target[index] = [model.add_var(var_type=BINARY) for _ in target_values]
    
    
        model.objective = minimize(
            xsum(
                bin_input_is_used_to_build_target[input_index][target_index] * input_values[input_index]
                    for input_index in range(0, len(input_values))
                    for target_index in range(0, len(target_values)))
        )
    
        for target_index in range(0, len(target_values)):
            model += xsum(bin_input_is_used_to_build_target[input_index][target_index] * input_values[input_index]
                           for input_index in range(0, len(input_values))) == target_values[target_index]
    
        for input_index in range(0, len(input_values)):
            model += xsum(bin_input_is_used_to_build_target[input_index][target_index] * input_values[input_index]
                          for target_index in range(0, len(target_values))) <= input_values[input_index]
    
        model.optimize()
    
        result = {}
    
        for target_index in range(0, len(target_values)):
            result[target_index] = [input_values[input_index]
                                        for input_index in range(0, len(input_values))
                                        if bin_input_is_used_to_build_target[input_index][target_index].x >= 0.99]
    
    
        return result
    
    
    if __name__ == "__main__":
    
        input_values = [1, 2, 1, 1, 1, 1, 3, 2, 5]
    
        target_values= [3, 4, 5, 5]
    
        result = solve(input_values, target_values)
    
        for i in range(0, len(result)):
            print(target_values[i], " : ", result[i])
    
        # 3: [2, 1]
        # 4: [1, 1, 2]
        # 5: [5]
        # 5: [1, 1, 3]
    Ответ написан
    2 комментария
  • Как изменить несколько переменных сразу?

    ayazer
    @ayazer
    Sr. Software Engineer
    ну так обновите метод чтоб обновлять сразу все значения что вам нужны
    UPDATE chats SET {name1}={value1}, {name2}={value2}, ...., {nameN}={valueN} WHERE chat_id = {chat_id}


    https://dev.mysql.com/doc/refman/8.0/en/update.html
    Ответ написан
  • Убрать все повторяющиеся элемента за O(n) времени?

    ayazer
    @ayazer
    Sr. Software Engineer
    используйте доп. структуру данных чтоб хранить кол-во вхождений каждого элемента в список. т.е. для каждого элемента в списке (сложность O(n)) нужно увеличить счетчик в этой структуре данных (в случ. с хеш таблицой это O(n) в худшем и О(1) в среднем). и потом еще раз пройтись по хештаблице и достать с нее все элементы где счетчик = 1 (сложность O(n)). в итоге даже сложность для худшего случая будет o(n + n + n) = O(n)

    те
    var inputArray = new[] { 1, 2, 3, 4, 5, 4, 3, 2, 1 };
    var set = new Dictionary<int, int>();
    
    foreach (var val in inputArray)
    {
        if (!set.ContainsKey(val))
        {
            set.Add(val, 1);
        }
        else
        {
            set[val] = set[val] + 1;
        }
    }
    
    var result = new List<int>();
    foreach (var val in set)
    {
        if (val.Value == 1)
        {
            result.Add(val.Key);
        }
    }
    
    return result; //[5]

    ^ можете считать примером на псевдокоде, читатся вроде должно без проблем
    Ответ написан
    2 комментария
  • Обход Binary-Tree, как сделать быстрее?

    ayazer
    @ayazer
    Sr. Software Engineer
    1) питон не умеет отбрасывать хвост. Использовать рекурсию я ЯП которые не умееют в хвостовую оптимизацию - так себе идея. Особенно на абстрактной задаче на обход дерева. Особенно если сразу сказали что дерево "сильно несбалансированное". Потому легким движением ваше решение превращается в тыкву.

    root1 = Node(1)
    cur_node = root1
    for i in range (0, 1000):
        cur_node.left = Node(i)
        cur_node = cur_node.left


    2) вот эти два дерева у вас выходят одинаковыми. Как графы - да, они одинаковы т.к. симметричны. Как деревья - нет, они разные.
    root1 = Node(1)
    root1.right = Node(2)
    root1.right.right = Node(3)
    
    root2 = Node(3)
    root2.left = Node(2)
    root2.left.left = Node(1)


    Так что сначала нужно пофиксить, а потом уже думать как сделать быстрее
    Ответ написан
  • Как управлять памятью в javascript?

    ayazer
    @ayazer
    Sr. Software Engineer
    это не относится в джаваскрипту, это типичная проблема когда данных слишком много чтоб с ними работать "в лоб".

    так что (если уж хочется ради интереса решить эту задачу через бинарный поиск) распиливайте дерево на несколько мелких. Ведь с каждым шагом область поиска сужается в 2 раза. Если все данные занимают 60Гб (как написал Сергей Соколов), то после первых 5 шагов искать нужно будет уже только в 3.25Гб. Как вариант - используйте 1 дерево чтоб сузить область поиска до того размера который уже влазит в память, и потом уже загружайте второе дерево и ищите в нем
    Ответ написан
    5 комментариев