Ответы пользователя по тегу C#
  • Wpf listview: как обновить только один элемент его?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    1) Список моделей хранить в ObservableCollection,
    2) В классе модели реализовать интерфейс INotifyPropertyChanged (можно сделать это в базовом классе)
    3) В свойствах модели в сеттере вбрасывать событие PropertyChanged с именем свойства:
    private string _name;
    public string Name
    {
        get
        {
            return _name;
        }
        set
        {
            if (_name != value)
            {
                _name= value;
                RaisePropertyChanged(nameof(Name));
            }
        }
    }
    
    // можно сделать в базовом классе, в котором и реализовать интерфейс INotifyPropertyChanged
    protected virtual void RaisePropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
    Ответ написан
    Комментировать
  • Как правильно открыть окно в другом приложении?

    lexxpavlov
    @lexxpavlov Автор вопроса
    Программист, преподаватель
    В описании функции SetForegroundWindow написаны условия, когда эта функция работает. В некоторых случаях почему-то в другое окно не передаётся клавиатурный фокус. Точнее, второй процесс, который открывает окно, не имеет фокуса. Почему-то в некоторых случаях это не мешает ему открывать активное окно (видимо, одно из других условий срабатывает), но в некоторых - не может сделать окно активным.

    Решение - симулировать нажатие клавиши в процессе, который будет открывать окно:
    private const byte VK_LMENU = 0xA4;
    private const byte KEYEVENTF_EXTENDEDKEY = 0x01;
    private const byte KEYEVENTF_KEYUP = 0x02;
    private const byte KEYSCAN_LALT = 0xB8;
    
    [DllImport("user32.dll")]
    internal static extern bool SetForegroundWindow(IntPtr hwnd);
    [DllImport("user32.dll")]
    private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo);
    
    public static void BringWindowToFront(IntPtr hwnd)
    {
        // симуляция нажатия клавиши ALT https://stackoverflow.com/a/13881647/1343405
        keybd_event(VK_LMENU, KEYSCAN_LALT, 0, 0);
        keybd_event(VK_LMENU, KEYSCAN_LALT, KEYEVENTF_KEYUP, 0);
    
        SetForegroundWindow(hwnd);
    }


    Полезные ссылки: вопрос, статья.
    Ответ написан
    Комментировать
  • В чём ошибка внутри этого кода?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    У вас ошибки указаны в сообщениях в студии:

    1) Operator '<' cannot be applied to operand of type 'Vector2' and 'int'
    direction - это Vector2, его нельзя сравнивать с числом. Нужно сравнивать direction.x < 0 или direction.y < 0 (или и то, и другое вместе, как вам нужно).

    2) ; expected
    После if должна быть инструкция, закончившаяся ; (или в фигурных скобках). У вас этого нет.

    И прислушайтесь советов Denis Gaydak!
    Если ещё можно написать такой код, как вы сделали, (хотя вы и не сделали :) ), то изменять его уже не получится - дольше времени разбираться с ним, чем исправлять.
    Сделайте такие методы: ProcessTouch(Touch touch), MoveFigureBy(int value), RotateFigure(), FallFigure() и их вызывайте в CheckUserInput(). Обратите внимание, что я в старте поместил ссылку на GameScript в переменную GridObject. Это важно, потому что метод FindObjectOfType ресурсоёмкий, а у вас он вызывается несколько раз в каждом Update (то есть, десятки раз в секунду!).

    Я позволил себе предложить вот такой код (я только исправил две ошибки, о которых вы говорили, и сделал рефакторинг):
    GameScript GridObject;
    
    void Start()
    {
    	GridObject = FindObjectOfType<GameScript>();
    }
    
    void Update () 
    {
        CheckUserInput();
    }
    
    void CheckUserInput()
    {
        if (Input.touchCount > 0) ProcessTouch(Input.GetTouch(0));
        if (Input.GetKeyDown(KeyCode.RightArrow)) MoveFigureBy(1);
        if (Input.GetKeyDown(KeyCode.LeftArrow)) MoveFigureBy(-1);
        if (Input.GetKeyDown(KeyCode.UpArrow)) RotateFigure();
        if (Input.GetKeyDown(KeyCode.DownArrow) || Time.time - fall >= fallSpeed) FallFigure();
    }
    
    void ProcessTouch(Touch touch)
    {
        if (touch.phase == TouchPhase.Began)
        {
            previousUnitPosition = new Vector2 (touch.position.x, touch.position.y);
        } else if (touch.phase == TouchPhase.Moved)
        {
            Vector2 touchDeltaPosition = touch.deltaPosition;
            direction = touchDeltaPosition.normalized;
    
            if (Mathf.Abs(touch.position.x - previousUnitPosition.x) >= touchSensitivityHorizontal && direction.x < 0 &&toucht.deltaPosition.y > -10 && touch.deltaPosition.y < 10) // на этой строке ошибка direction < 0
            {
                // что делать???
            }      
        } else if (touch.phase == TouchPhase.Ended)
        {
    
        }
    }
    void MoveFigureBy(int value)
    {
        transform.position += new Vector3(value, 0, 0);
        if (CheckIsValidPosition()) 
        {
            GridObject.UpdateGrid(this);
        } else 
        {
            transform.position += new Vector3(-1 * value, 0, 0);
        }
    }
    void RotateFigure()
    {
    	if (allowRotation) 
        {
            if (limitRotation) 
            {
                if (transform.rotation.eulerAngles.z >= 90) {
                    transform.Rotate(0,0,-90);
                } else 
                {
                    transform.Rotate(0,0,90);
                }
            } else 
            {
                transform.Rotate (0,0,90);
            }
            if(CheckIsValidPosition()) 
            {
                GridObject.UpdateGrid(this);
            } else 
            {
                if (limitRotation) 
                {
                    if (transform.rotation.eulerAngles.z >= 90) 
                    {
                        transform.Rotate(0,0,-90);
                    } else 
                    {
                        transform.Rotate (0,0,90);
                    }
                } else 
                {
                  transform.Rotate (0,0,-90);
                }
            }
        }
    }
    void FallFigure()
    {
        transform.position += new Vector3(0, -1, 0);
            
        fall = Time.time;
    
        if (CheckIsValidPosition()) 
        {
            GridObject.UpdateGrid(this);
        } else 
        {
              transform.position += new Vector3(0, 1, 0);
              GridObject.DeleteRow();
              if (GridObject.CheckIsAboveGrid (this))
              {
                  GridObject.GameOver ();
              }
              enabled = false;
              GridObject.SpawnNextFigure();
        }
    }
    Ответ написан
    Комментировать
  • Как правильно называть следующий синтаксис?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    SomeClass obj = new SomeClass();
    Нужно понимать, что происходит в этой строке. В этой строке происходит две вещи:
    1) создаётся экземпляр класса SomeClass и размещается в куче (специальном месте для хранения объектов). Сами экземпляры не имеют собственных имён, только адрес в куче.
    2) объявляется локальная переменная, и в эту переменную присваивается адрес вновь созданного объекта. Имя именно у переменной, а не у объекта!
    Теперь с объектом можно работать по ссылке, например, присваивать поля и свойства и вызывать методы. Может быть несколько разных ссылок на один объект, но одна ссылка не может быть на несколько объектов (в ссылочной переменной - просто конкретный адрес).

    Теперь разберёмся с терминами "экземпляр" и "объект". Экземпляр является объектом, но не все объекты являются экземплярами определённого класса (например, структуры - это объекты, но не экземпляры класса. Чтобы лучше понять это, нужно изучить различие переменных по ссылке и по значению). В языке C# практически всё является объектом (даже примитивные типы могут рассматриваться как объекты). В том числе, и экземпляры класса. Класс можно считать "шаблоном", который указывает правила создания объекта (количество и тип полей в объекте).

    Статические элементы класса не принадлежат ни одному объекту (экземпляру), можно сказать, эти элементы принадлежат самому классу. Поэтому, нельзя обратиться к статическому элементу через переменную экземпляра, но можно обратиться просто по имени элемента в коде метода. В том видеоуроке объяснено неверно.

    главный вопрос, как нужно комментировать эту строку: "my.age = 5"?

    Присвоить значение 5 полю age объекта на который ссылается переменная my (зачеркнутый текст обычно не говорится, но подразумевается). Вместо слова "объекта" можно сказать "экземпляра", это тоже верно (потому что экземпляр - это тоже объект).
    Ответ написан
    5 комментариев
  • Чем реально полезным можно заняться школьнику знающему программирование?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    >Хорошо знаю Си-Шарп и Юнити.
    Ну так в чём дело? Сделайте отличную игру (или не отличную, но свою). Все школьники (и не только школьники) мечтают об этом. Я не шучу, это может стать полезным, (частично) приятным и (есть шанс) прибыльным. А раз вы школьник, то у вас полно свободного времени (не нужно зарабатывать на хлеб).
    Но главное - решить дойти до конца, до релиза, до победы. Например, возьмите любую любимую игру (небольшую) и сделаете клон (возможно, доработать под себя).
    Либо найдите команду разработчиков, которые ищут программиста (вагон таких предложений). Но нужно выбрать хорошую команду (чтобы была похожа на серьёзную).

    Или другой вариант предложил Александр Тер - сделать что-нибудь полезное для общества. Как пример, был подобный случай несколько лет назад.
    Ответ написан
    1 комментарий
  • Как сформировать Excel на основании Json?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Проще всего массив нарядов преобразовать в csv. А потом из csv можно преобразовать в xls с помощью, например, библиотеки EPPlus (простой пример использования).

    Само преобразование лучше произвести в отдельном методе, а не в AjaxTest4(). Лучше даже в отдельном классе, имхо.
    Ответ написан
  • Какие архитектурные подходы выбрать для разработки клиент-серверной игры?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    так и не осознал, что хранится в БД, а что - в RAM ... автоматические системы кеширования/сброса в БД?

    В БД хранится вся информация мира, в текущий момент. Представьте, что сервер внезапно "умер", вся инфа в памяти исчезла, и теперь доступна только та инфа, которая сейчас в БД. Но получить инфу довольно долго, поэтому, используются кэши, иногда - многоуровневые. Если бы БД имела бесконечную скорость работы, то кэш был бы не нужен. Но, к сожалению, кэш необходим. В идеале, в кэше находится вся та же инфа, что и в БД. Но сложнейшая задача - инвалидация кэша (в БД инфа уже изменилась, а в кэше - нет, ещё хуже - в одном кэше тоже изменилась, а в другом - нет). Для того, чтобы потом не собирать баги лопатами, то придётся создавать автоматические системы кеширования/сброса.
    Почитайте статьи "Архитектура высоконагруженных приложений. Масштабирование распределенных систем" (части 1 2) от Badoo.

    Как, собственно, производить синхронизацию клиента и сервера?

    Весь мир только на сервере, у клиента нужны только доступные (видимые) игроку объекты, иначе игроки узнают "лишнюю" инфу (например, в World of Tanks есть способы узнать "невидимые" танки). Но, к сожалению, так обычно не получается. Клиенту приходится знать чуть о большем количестве объектов, для того, чтобы прогнозировать их поведение. Но в космических играх попытаться можно сделать видимость объектов. Вы сказали про сенсоры корабля, эта очень хорошая мысль - объект исчез из сенсора, то пусть клиент удаляет этот объект. Если в дальнейшем объект становится в сенсоре, то пусть об этом сервер сообщит клиенту (или не сообщит, например, корабль включил маскировку, тогда клиент вообще не знает, что "кто-то" есть). Это можно добавить в геймдизайн - если объект попадает в зону сенсора, то сенсор увидит не в тот же миг, а через некоторе время, в зависимости от харакетристик сенсора (но не меньше пинга, хе-хе).
    Почитайте серию статей "Сетевое программирование для разработчиков игр" (части 1 2 3), а также блог 0fps.net (на английском, нет нормального содержания, но есть сильные статьи). Ещё полезнейшая статья "Борьба с читерами в онлайн-играх: 22 «нужно» и «нельзя»".

    создавать на клиенте экземпляр той же симуляции мира, что и на сервере

    На клиенте создавать серверный мир не нужно, но и полностью отделяться тоже не стоит. Часть кода между сервером и клиентом будет общим. И чем больше, тем легче потом разрабатывать и клиент, и сервер. Помните про наследование с полиморфизмом, про общие проекты в решении.
    Сервер не должен ничего знать про Unity3d, да и клиент игровую логику должен делать без использования инструментов Unity (про это ещё говорит TheShock). Так будет гораздо проще в дальнейшем.

    может ли что-нибудь дать использование ASP.NET (возможно core) в качестве основы, или для таких целей его использование бессмысленно?

    ASP.NET не нужен, имхо, он мало пользы может дать игровому серверу. Я бы начал делать сервер на .NET Core (можно и .NET Framework, просто сложнее будет деплоить. Подумайте про Azure).

    Дмитрий Александров предложил про чанки. Мне кажется, что это хорошая мысль. Почитайте статью "Введение в октодеревья", возможно, это решит проблему с длинными расстояниями. Чанки будут нужны, потому что однажды один сервер не сможет "осилить" весь мир, придётся разделять его.
    Ответ написан
    1 комментарий
  • Какой простой и надежный способ хэширования пароля ASP.NET MVC?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Для хеширования пароля лучше всего использовать BCrypt (пример).
    Если не нравится BCrypt, то можно использовать SHA512 - он уже есть в .NET Framework.
    Ответ написан
    Комментировать
  • Какой уровень математики нужен в GameDev (Unity, UE4)?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Математика в gamedev нужна в любом случае. Даже если делается маленькая игрушка, то нужно хотя бы понимать, как работает пропорция...
    Но вот вопрос - какой уровень математики нужен в gamedev.
    TL;DR: очень желателен средний уровень (хотя бы уровень 11 класса).
    Долгое объяснение:
    1) Игру можно делать вообще без математики - движок берёт на себя сложную математику. Но чем больше игра, тем больше будет нужно понимание математики - математика может пригодиться при расчёте выстрелов, при расчёте "хитрого" поиска пути, обязательно пригодится в при разработке ИИ, и уж точно пригодится при расчёте баланса (но это работа гейм-дизайнера, а не программиста).
    2) Причём, нужно именно понимание - не столько умение решать типовые задачки, сколько способность анализировать формулы придумывать свои. Например, какую-то фишку можно сделать несколькими способами, и вероятнее всего, более производительным будет тот способ, который лучше использует математику. Помимо обычной математики, может пригодиться геометрия. И уж точно пригодится булева алгебра.
    3) Начиная с восьмого класса, в школе учат не только считать тривиальные задачки, но и развивают так называемое "математическое мышление". Особенно этому учат "задачки со звёздочкой" (более сложные, но необязательные, не знаю, во всех ли учебниках есть такие). Именно математическое мышление позволяет лучше продумывать алгоритмы. (N.B. рекомендую почитать Я.И.Перельмана с его "Занимательной математикой")
    4) ААА-игры делаются не одним-двумя программистами, при разработке ААА-игр программистов используются десятки (а всего разработчиков может быть сотни, от гейм-дизайнеров до композиторов). Все из них не обязательно должны знать математику хорошо. Но если не знать, то вероятность развиться "повыше" - то сложнее.
    5) При некоторых играх математика почти не нужна (при использовании приличного движка), а в некоторых играх математика точно нужна.
    6) Программирование - техническая наука. Да, "гуманитарии" тоже могут стать программистами, но им будет сложнее. Ещё Ломоносов сказал: "Математика ум в порядок приводит" - в нашем классе математики в школе была такая картинка на стене. И я как учитель могу подтвердить эту мысль.

    Итог.
    Можно ли сделать игру без математики? Можно.
    Математика поможет разработке игры? Почти наверняка.
    Хочется развиваться хотя бы до сениора? Учи математику.
    Ответ написан
    Комментировать
  • C#. Как удалить часть строки которая идет после последнего символа, например запятой?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    string aaa = "Привет, что делаешь, как дела";
    int pos = aaa.LastIndexOf(',');
    string bbb = aaa.Substring(pos);
    aaa = aaa.Substring(0, pos);
    Ответ написан
  • Можно ли откомпилировать код в Visual Studio 2015/2017 без создания проекта?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Можно использовать онлайн-компилятор, например
    https://www.tutorialspoint.com/compile_csharp_onli...
    Ответ написан
    Комментировать
  • Порядок изучения C#?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Неплохая книга Бена Ватсона "С# 4.0 на примерах" - много примеров, как делать конкретные вещи, в том числе, по WPF.

    Программирование зиждется на трёх китах - 1) знание (синтаксис) языка, 2) алгоритмы и 3) архитектура. Причём, последние не связаны с языком. Читайте не только о языке, но и общие знания - паттерны, архитектура, алгоритмы. В большинстве классических книг примеры написаны не на c#, но их чтение сильно развивает как программиста.
    Мартин Р. Чистый код. Создание, анализ и рефакторинг рекомендую прочитать хотя бы до 12 главы, дальше - углубление. Первые главы дают шикарный базис для построения архитектуры - почему писать так, а не иначе. Примеры на Java, но этот язык довольно сильно похож на C#.
    Фаулер М. Рефакторинг. Улучшение существующего кода классическая книга
    Гамма Э и др. Приёмы объектно-ориентированного проектирования суперклассическая книга, так называемая "банда четырёх"
    Скиена С. Алгоритмы. Руководство по разработке книга о алгоритмах, проще, чем известная книга Д. Кнута

    Ну и посмотрите этот список книг.
    Ответ написан
    Комментировать
  • Есть ли готовые либы для JS, PHP, C#, Java, ObjC/Swift для манипуляции с датой и временем, типа красиво писать "3 часа назад" и т.д.?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Вы хотите одну библиотеку, в которой все языки? Так не бывает, библиотека связана с конкретным языком, но на некоторых языках есть порты. Языков несколько сотен (1, 2), вы хотите, чтобы автор эдакой убер-библиотеки сделал все языки?

    >Но может следует просто взять готовое?
    Конечно, готовое, если уже есть и если приличного качества.
    Stalker_RED показал библиотеки для js и php. Для c# есть https://github.com/Eonasdan/MomentSharp
    Ответ написан
    3 комментария
  • Как правильно заполнить List данными?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    var names = new[] { "n1", "n2", "n3" };
    var descriptions = new[] { "d1", "d2", "d3" };
    var companies = new[] { "c1", "c2", "c3" };
    var products = Enumerable.Range(0, names.Length-1)
                  .Select(i => new Product { Name = names[i], Description = descriptions[i], Company = companies[i]})
                  .ToList();

    Всё равно придётся создавать объект, в который нужно передать конкретное значение данных. Лучше циклом, имхо.
    Ответ написан
    Комментировать
  • C чего начинать обучение C# и .net платформы?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Эндрю Троелсен Язык программирования C# 6.0 и платформа .NET 4.6
    Это большая и сильная книга о платформе .NET и языке C#. Книга предназначена для профессионалов, то есть, не для новичков - в ней нет общей информации о программировании (ООП, архитектуре и пр.), но есть о том, как это всё использовать в языке C#. В ней описано практически всё - синтаксис языка, создание консольных и оконных программ (WPF), клиент-серверные приложения.
    Книга дорогая, можно поискать предыдущее издание (C#5.0, C#4.5).
    Ответ написан
    2 комментария
  • Как преобразовать generic-объект в не-generic?

    lexxpavlov
    @lexxpavlov Автор вопроса
    Программист, преподаватель
    В C# нет автоматического преобразования generic-объекта в не-generic. Если такое потребуется, то необходимо сделать это самостоятельно в этом же классе (или в базовом классе). В данном коде преобразование реализовано в классе AbstractProcessor:
    using System;
    using System.Collections.Generic;
    
    class Program
    {
        static void Main(string[] args)
        {
            var list = new List<IProcessor>()
            {
                new Processor(), 
            };
            IProcessor o = new Processor();
            Console.ReadKey();
        }
    }
    
    interface INode { }
    interface IResult { }
    
    interface IProcessor
    {
        INode Get();
        void Print(IResult result);
    }
    interface IProcessor<out T, in R> : IProcessor where T : class, INode where R : class, IResult
    {
        new T Get();
        void Print(R result);
    }
    
    abstract class AbstractProcessor<T, R> : IProcessor<T, R> where T : class, INode where R : class, IResult
    {
        public abstract T Get();
        public abstract void Print(R result);
    
        // Преобразование в не-generic тип
        void IProcessor.Print(IResult result)
        {
            Print(result as R);
        }
    
        INode IProcessor.Get()
        {
            return Get();
        }
    }
    
    class Node : INode { }
    class Result : IResult { }
    class Processor : AbstractProcessor<Node, Result>
    {
        public override Node Get() { return null; }
        public override void Print(Result result) {}
    }
    Ответ написан
    Комментировать
  • Есть ли функции с управляемым контекстом?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Используй словарь Dictionary<KeyCode, bool> вместо нескольких переменных. Это если флаги нужны ещё где-то. А если эти флаги нужны только в Update(), то они и не нужны:
    int GetKey(KeyCode key) // 1 or 0
    {
        return Input.GetKeyDown(key) ? 1 : 0;
    }
    void Update()
    {
        int hor = GetKey(KeyCode.A) - GetKey(KeyCode.D);
        int ver = GetKey(KeyCode.W) - GetKey(KeyCode.S);
        transform.position += new Vector3(hor, ver, 0) * CameraSpeed;
    }
    Ответ написан
  • Предупреждение CA2202 VS2105 и как его исправить?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Использовать using нормально, для этого его и придумали.

    Анализатор показывает предупреждение CA1063? В этом предупреждении он поясняет, что ему не нравится, и предлагает, что сделать. (Это предупреждение возникает в нескольких местах, и текст в них разный.)
    Ответ написан
    Комментировать
  • Как разделить данных из Listbox?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Метод-расширение для разделения на несколько частей:
    using System.Collections.Generic;
    using System.Linq;
    
    namespace Helpers
    {
        public static class ArrayHelperExtensions
        {
            public static IEnumerable<IEnumerable<T>> Split<T>(this T[] array, int size)
            {
                for (var i = 0; i < (float) array.Length/size; i++)
                {
                    yield return array.Skip(i*size).Take(size);
                }
            }
        }
    }

    Теперь берём массив и делим его на нужное кол-во частей:
    var num = 3;
    var parts = listbox1.Items.Split(num);

    Дальше осталось записать в файлы.

    Решение отсюда.
    Указанный способ не самый быстрый, есть более быстрые способы - см. тут.
    Ответ написан
    Комментировать
  • Как возвращать ошибки из сервисов?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Исключение - это исключительная ситуация, которая не должна происходить в обычном варианте работы. Но если возможно отсутствие объекта, и это нормальная ситуация (неисключительная), то это не исключение, лучше вернуть null.
    Пример первый - метод должен вернуть текущего юзера. Конечно, текущий юзер должен быть, если его нет - это исключение.
    Пример второй - ищется комментарий к сообщению. Ни одного комментария никто не оставил, и если искать найденный юзер комментария - то юзер не найдётся, но это не исключение - нормально вернуть null.
    Но возможно, что лучше код сделать так, чтобы вызов этого метода не вызывался бы.
    Ответ написан
    Комментировать