Ответы пользователя по тегу C#
  • Может ли быть переход объекта от SOH to LOH и наоборот? Если да, то какие процессы в это время происходят? Простой переход или что-нибудь ещё?

    ayazer
    @ayazer
    Sr. Software Engineer
    нет, не может

    upd:
    не нужно путать общий размер занимаемой памяти и размер объекта. В loh попадет условный массив на 100мб/ большая строка. Но объект который ссылается на это - нет, т.к. в нем будет только ссылка весом в пару байт.

    подозреваю что вы думали о чем-то таком

    public class TestClass
        {
            public byte[] Bytes;
    
            public TestClass(byte[] bytes)
            {
                Bytes = bytes;
            }
    
            public void Upd()
            {
                Bytes = new byte[101 * 1024 * 1024];
            }
        }
    
    ...
    
        static void Main(string[] args)
        {
            var data = new TestClass[3];
    
            for (int i = 0; i < 3; i++)
            {
                data[i] = new TestClass(new byte[1]);
            }
    
            data[1].Upd();
        }


    но нет, это не заставит переиестить объект с soh -> loh, т.к. в loh попадет только массив, а в объекте будет просто ссылка. И если заглянуть в память - это видно

    5f23ca2621fda807535079.png
    Ответ написан
    3 комментария
  • Как правильно вписать Bool в If?

    ayazer
    @ayazer
    Sr. Software Engineer
    судя по ошибке - enemyStatus это не метод

    if(other.tag == "Player" && Input.GetKeyDown(activateEnemies) && !enemyStatus)
    Ответ написан
    Комментировать
  • Что хранит в себе неинициализированная переменная в C#?

    ayazer
    @ayazer
    Sr. Software Engineer
    если переменная объявлена, но ЕЩЕ не инициализирована - там будет дефолтное значение (null для классов, конкретное значение для структур (см. default)). Проверить это можете в прямо в дебаггере.

    обратится к переменной которая ЯВНО не инициализирована в момент обращения (как раз та ситуация когда в ней в с++ находится какой-то хлам) - нельзя, т.к. это считается потенциальным багом и такой код даже не скомпилируеться. (подозреваю что вопрос был как-раз про эту часть)
    Ответ написан
    Комментировать
  • Как правильно присвоить локальное значение переменной в C#?

    ayazer
    @ayazer
    Sr. Software Engineer
    float result;

    Если пользователь введет в качестве операции не что-то с { +, -, *, / } - выйдет неопределенное поведение т.к. result будет не инициализирован в момент
    string value = $"Результат: {result}";

    Либо делайте
    float result = 0f;

    Либо (что правильней) - не допускайте возможности такой ситуации вообще
    if (o == "+")
                    {
                        result = add(f, s);
                    }
                    else if(o == "-")
                    {
                        result = subtraction(f, s);
                    }
                    else if(o == "*")
                    {
                        result = multiplication(f, s);
                    }
                    else if(o == "/")
                    {
                        result = division(f, s);
                    }
                    else
                          throw new Exception($"Unexpected operation '{o}'");
    Ответ написан
    Комментировать
  • Где находится статический класс в памяти?

    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
    ну для начала исправить на

    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
    private static string[] _elementNames = new[] { "SiO2 (β-кварц)",  "and", "more"};
    
    ....
    
    if (_elementNames.Contains(name))
    {
        if (curTemp <= 846.15)
        {
            h = -217.75F; 
            s = 10F;
            a = 11.22F; 
            b = 8.2F; 
            c = -2.7F;
        }
        else if (....) { ....}
        ....
    }


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

    ayazer
    @ayazer
    Sr. Software Engineer
    async void
    вернет управление обратно, не дожидаясь выполнения асинхронного кода внутри. вам же нужно возвращать таску

    public async Task DownloadVideo1080PAsync(string path, ProgressBar progressBar, string link)
    {
        await ytClient.Videos.Streams.DownloadAsync(audioInfo, Path.Combine(newLink, $"audio.wav"));
        await ytClient.Videos.Streams.DownloadAsync(videoInfo, Path.Combine(newLink, $"video.mp4"), progressHandler);
    }
    
    public Task MergeAudioVideoAsync(string link)
    {
        return ffmpeg.ExecuteAsync($@"-i video.mp4  -i audio.wav -c:v copy -c:a aac newVideo.mp4");
    }


    ....
      await DownloadVideo1080PAsync(....);
      await MergeAudioVideoAsync(...);
    ....
    Ответ написан
    Комментировать
  • Нужна помощь с решением задачи. Необходимо посчитать смену знаков. В чем моя ошибка?

    ayazer
    @ayazer
    Sr. Software Engineer
    ну так запустите дебаггер и посмотрите. тут больше чем 1 ошибка.

    1) можете начать проверять с варианта когда i==2 и j==4. тогда array[i++,j++] уже выходит за границу
    2) array[i++,j++] - вы уверены что вам нужно сравнивать значения именно по диагонали?
    3) i++ это постинкремент который изменяет значение. подозреваю что вы хотели просто сравнить со следующим
    4)
    array[i,j] < 0 && array[i++,j++] >= 0 || array[i,j] >= 0 && array[i++,j++] < 0
    запустите в дебаггере/интерактивной консоли и проверьте действительно ли это будет работать как вы думали. подозреваю что вы хотели получить все-же другой результат
    Ответ написан
    1 комментарий
  • Как работает .NET?

    ayazer
    @ayazer
    Sr. Software Engineer
    код превращается в IL, который уже будет превращаться в машинный по мере необходимости (см. JIT компиляцию). Т.е. по сути первый вызов метода будет происходить чуть дольше т.к. будет происходить оптимизация и компиляция IL кода под реальную аппаратную платформу. После чего все последующие вызовы будут выполняется быстрее. Если такой вариант по каким-то причинам не подходит - есть ngen который позволяет сразу скомпилировать код под известную платформу (выиграв на холодных запусках, по потеряв в переносимости). И в этом случае jit компиляция во время работы приложения уже выполнятся не будет.

    В CLR не входит CIL?

    не совсем понял вопрос. cil/msil/il - просто промежуточный в который превращается код на С#/F#/VN.NET/etc. Можно расценивать его как ассемблер для .нета. Мало того, никто не запрещает написать свой DSL, который будет генерировать IL, который в свою очередь будет работать везде где работает .нет

    JIT запускается каждый раз при сборке проекта или только один раз чтобы запомнить архитектуру платформы?

    оба варианта нет. jit компиляция = just-in-time и запускается прямо во время работы приложения. как-раз она и превращает IL код в нужный набор машинных кодов.
    Ответ написан
    3 комментария