Ответы пользователя по тегу C#
  • Код завершается с кодом 0, без выполнения самого кода?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Код ноль - это успешное выполнение.

    Если значение отличается от нуля, значит программа завершила работу с ошибкой.
    Ответ написан
    6 комментариев
  • Как извлечь и обработать данные из запускающего файла собственного расширения?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Прочитать из аргументов командной строки, примерно так:
    static class Program
    {    
      [STAThread]
      static void Main(string[] args) // <---
      {
        // args - будет содержать параметры запуска программы
      }
    }

    либо:

    string[] args = Environment.GetCommandLineArgs();
    Ответ написан
    1 комментарий
  • C# - Как удалить символ из строки при посимвольной обработке строки в цикле?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Проще всего использовать регулярные выражения, если это допустимо:
    string value = "ab+0.1973-1.1";
    string result = Regex.Replace(value, @"(\.\d{2})\d+", "$1");

    Если использовать цикл, то нужно создавать новую строку, но вместо string лучше использовать StringBuilder, т.к. при добавлении данных к string строка постоянно будет пересоздаваться, что в конечном итоге может негативно отразиться на производительности:

    string inputString = "ab+0.1973-1.1";
    var result = new StringBuilder();
    bool hasDot = false;
    int digits = 0;
    
    foreach(char ch in inputString)
    {
      if (char.IsDigit(ch) && hasDot)
      {
        digits++;
      }
      else
      {
        digits = 0;
        hasDot = (ch == '.');
      }
    
      if (digits <= 2)
      {
        result.Append(ch);
      }
    }
    
    Console.WriteLine(result.ToString());

    Если хорошо подумать и если это допустимо, то задачу можно решить с одним только StringBuilder (одним экземпляром), в котором изначально будет строка для обработки, используя метод Remove для удаления ненужных данных. При такой реализации, будет использоваться цикл for.
    Ответ написан
    Комментировать
  • Нужен ли установленный .NET для запуска программы?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Для Windows XP нужен .NET Framework 4, выше уже не подойдет.
    Со старшими версиями систем проблем возникнуть не должно.

    https://docs.microsoft.com/ru-ru/dotnet/framework/...

    Как вариант, можно сделать мультиплатформенное приложение, для новых платформ использовать новые версии .NET, а для XP писать вставки под .NET 4.0. Код может быть не очень удобно поддерживать:

    #if NET40
    // код для .NET 4.0
    #else
    // код для остальных версий
    #enif

    Если делать так, то при наличии возможности, лучше всего использовать .NET Core.
    Ответ написан
    4 комментария
  • Как на основе исходного кода сделать консольное приложение?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    1. Создаем консольное приложение.
    2. Добавляем пакет.
    3. Пользуемся.
    Ответ написан
    2 комментария
  • Как отключить encode в WebClient UploadValues?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Если параметр в Url, то можно сделать экземпляр Uri и отключить кодирование:
    var url = new Uri("http://site.com/index.php?199|&param=1", true);
    // ...
    var response = wb.UploadValues(url, "POST", data);

    Без кодирования параметров с помощью HttpClient
    using (var client = new HttpClient())
    {
      var url = new Uri("http://site.com/index.php?199|&param=1", true);
      var data = new StringBuilder();
      data.AppendLine("abc=199|");
    
      using (var content = new StringContent(data.ToString(), Encoding.UTF8, "application/x-www-form-urlencoded"))
      {
        using (var request = new HttpRequestMessage(HttpMethod.Post, url))
        {
          request.Content = content;
    
          using (var response = client.SendAsync(request).Result)
          {
            response.EnsureSuccessStatusCode();
    
            // var result = await response.Content.ReadAsStringAsync();
            var result = response.Content.ReadAsStringAsync().Result;
          }
        }
      }
    }

    Ответ написан
    3 комментария
  • Почему не получается вычесть время?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Еще DateTime.Subtract можно использовать:

    WorkTimeLabel.Content = $"Рабочее время: {DateTime.Now.Subtract(timeStart).ToString(@"hh\:mm")}";

    Разделители и прочие «непонятные» символы лучше экранировать (слешем, как показано в примере).

    Если timeStart будет раньше на 24 часа, то в формате hh:mm эта информация не отразится. Можно использовать такой вариант:

    WorkTimeLabel.Content = "Рабочее время: " + 
      (DateTime.Now - timeStart).ToString(@"d\д\ hh\:mm").TrimStart('0', 'д').Trim();

    См. также: Stopwatch
    Ответ написан
    Комментировать
  • Для чего нужны спецификаторы доступа в C#/Java и др. подобных языках?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Модификаторы помогают организовать работу с кодом. Избавить от потенциальных проблем неправильного использования кода, особенно малоопытными программистами. Иногда работаю с PHP, модификаторов типа internal очень сильно не хватает, приходится извращаться, чтобы другим работать с кодом было удобно; чтобы не было возможность залезть туда, куда не нужно и нарушить логику работы; чтобы на поверхности все выглядело проще, чем есть на самом деле.

    Чем сложнее проект, чем больше людей работают с кодом, тем сильнее потребность в порядке, изоляции отдельных участков проекта.

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

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Действие выполнять в отдельном методе, а потом просто вызвать этот метод повторно. Примерно так:
    static Action lastAction = null;
    
    static void AnyAction()
    {
      Console.WriteLine("Выполняю какое-то действие. Не отключайтесь...");
      Thread.Sleep(3000);
    }
    
    static void Repeat()
    {
      Console.WriteLine("Хотите повторить? [Д/н]");
    
      if (char.ToUpper(Console.ReadKey().KeyChar) == 'Д')
      {
        Console.WriteLine();
        lastAction();
        Repeat();
      }
    }
    
    static void Main(string[] args)
    {
      lastAction = AnyAction;
      lastAction();
      Repeat();
    }

    Или использовать очереди и добавлять действие в очередь при необходимости выполнить повтор:

    static Queue<Action> actions = new Queue<Action>();
    
    static void AnyAction()
    {
      Console.WriteLine("Выполняю какое-то действие. Не отключайтесь...");
      Thread.Sleep(3000);
    }
    
    static void Main(string[] args)
    {
      actions.Enqueue(AnyAction);
    
      while (actions.Count > 0)
      {
        actions.Dequeue()();
    
        Console.WriteLine("Хотите повторить? [Д/н]");
    
        if (char.ToUpper(Console.ReadKey().KeyChar) == 'Д')
        {
          Console.WriteLine();
          actions.Enqueue(AnyAction);
        }
      }
    }
    Ответ написан
    1 комментарий
  • Как сделать solution explorer в С#?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Какие нужны классы - зависит от задачи. Чтобы вывести список каталогов и файлов, дополнительные классы не нужны. Код может быть примерно таким:

    treeView1.Items.Clear();
    GetFiles("C:/Windows/Microsoft.NET", null);

    private void GetFiles(string path, TreeViewItem parent)
    {
      var node = new TreeViewItem() { Header = System.IO.Path.GetFileName(path) };
          
      if (parent == null)
      {
        treeView1.Items.Add(node);
      }
      else
      {
        parent.Items.Add(node);
      }
    
      var attr = System.IO.File.GetAttributes(path);
    
      if (attr.HasFlag(System.IO.FileAttributes.Directory))
      {
        var directories = System.IO.Directory.GetDirectories(path);
    
        foreach (var dir in directories)
        {
          GetFiles(dir, node);
        }
    
        var files = System.IO.Directory.GetFiles(path);
    
        foreach (var file in files)
        {
          node.Items.Add(System.IO.Path.GetFileName(file));
        }
      }
    }
    Ответ написан
    2 комментария
  • C# Xml Как занести в массив соответствующие элементы дерева?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Взять head и перебирать дочерние узлы, которые можно найти в свойстве ChildNodes:
    var xml = @"<head>
    <block1>
     <block_header></block_header>
     <block_picture></block_picture>
     <block_text></block_text>
    </block1>
    <block2></block2>
    <block3>
     <block_header></block_header>
     <block_picture></block_picture>
     <block_text></block_text>
    </block3>
    </head>";
    
    var doc = new XmlDocument();
    doc.LoadXml(xml);
    
    var head = doc.SelectSingleNode("/head");
    
    var list = new List<string>();
    
    foreach (XmlNode node in head.ChildNodes)
    {
      list.Add(node.Name);
      // node.InnerXml - содержимое узла
      Console.WriteLine("{0}={1}", node.Name, node.InnerXml);
    }
    
    // в коллекции list будет список имен дочерних узлов корневого узла

    Всех детей, при необходимости, можно перебрать рекурсией, или с помощью стека:

    var doc = new XmlDocument();
    // определение переменной xml см. в предыдущем коде
    doc.LoadXml(xml);
    
    // создаем стек
    var stack = new Stack<XmlNode>();
    
    // добавляем в стек корневой элемент
    stack.Push(doc.SelectSingleNode("/head"));
    
    // var list = new List<string>();
    
    // перебираем все элементы стека
    while(stack.Count > 0)
    {
      // берем верхний элемент и удаляем его и стека
      var node = stack.Pop();
    
      // выводим
      // если требуется, можно добавить в коллекцию
      // list.Add(node.Name);
      Console.WriteLine("Node: {0}, childs: {1}", node.Name, node.ChildNodes.Count);
    
      Console.WriteLine(node.InnerXml);
    
      // если есть дети, добавляем их в стек
      if (node.ChildNodes.Count > 0)
      {
        // берем с конца, чтобы сохранить порядок
        for (int i = node.ChildNodes.Count - 1; i >= 0; --i)
        {
          stack.Push(node.ChildNodes[i]);
        }
      }
    }
    Ответ написан
  • C# XML Как проверить существование узла?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    using System.Xml;
    var xml = @"<head>
     <block1></block1>
     <block2></block2>
     <block3></block3>
    </head>";
    
    var doc = new XmlDocument();  
    doc.LoadXml(xml);
    
    var node = doc.SelectSingleNode("/head/block3");
    
    if (node != null)
    {
      Console.WriteLine("Узел существует!");
    }
    else
    {
      Console.WriteLine("Узел не найден...");
    }
    Ответ написан
    1 комментарий
  • Каким сниппетом можно отправить следующий POST запрос на C#?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    using System.Net.Http;
    using System.Text;

    using (var client = new HttpClient())
    {
      var url = "https://dns.api.gandi.net/api/v5/zones/93cc9312-a214-408b-a75b-9d4172984746/records";
    
      // можно просто строку (string) сделать, как будет удобно
      var data = new StringBuilder();
      data.AppendLine("www IN A 192.168.0.1");
      data.AppendLine("    IN A 192.168.0.2");
      data.AppendLine("    IN A 192.168.0.2");
      data.AppendLine("@   IN MX 10 spool.mail.gandi.net.");
    
      using (var content = new StringContent(data.ToString(), Encoding.UTF8, "text/plain"))
      {
        // HttpMethod.Post, если нужен POST
        using (var request = new HttpRequestMessage(HttpMethod.Put, url))
        {
          // request.Headers.Authorization = new AuthenticationHeaderValue("", "");
          request.Headers.Add("X-Api-Key", "$APIKEY");
    
          request.Content = content;
    
          // using (var response = await client.SendAsync(request)
          using (var response = client.SendAsync(request).Result)
          {
            // выбросить исключение, если сервер вернул ошибку
            response.EnsureSuccessStatusCode();
    
            // var result = await response.Content.ReadAsStringAsync();
            var result = response.Content.ReadAsStringAsync().Result;
            // в result будет ответ сервера
          }
        }
      }
    }
    Ответ написан
    2 комментария
  • Как в WPF скрыть кнопки при нажатии?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Поместить кнопки в контейнер и менять статус видимости у контейнера:
    <Button Content="Ok" HorizontalAlignment="Left" VerticalAlignment="Top" 
      Width="75" Margin="0,75,0,0" 
      Click="Button_Click"
    />
    
    <WrapPanel Name="Buttons" Orientation="Horizontal">
      <Button Name="Button1" Content="Button" HorizontalAlignment="Left" 
        VerticalAlignment="Top" Width="75"
      />
      <Button Name="Button2" Content="Button" HorizontalAlignment="Left" 
        VerticalAlignment="Top" Width="75" 
      />
      <Button Name="Button3" Content="Button" HorizontalAlignment="Left" 
        VerticalAlignment="Top" Width="75" 
      />
      <Button Name="Button4" Content="Button" HorizontalAlignment="Left" 
        VerticalAlignment="Top" Width="75"
      />
    </WrapPanel>

    private void Button_Click(object sender, RoutedEventArgs e)
    {
      Buttons.Visibility = Visibility.Hidden; // Visibility.Visible
    
      /*
      if (Buttons.Visibility == Visibility.Hidden)
      {
        Buttons.Visibility = Visibility.Visible;
      }
      else
      {
        Buttons.Visibility = Visibility.Hidden;
      }
      */
    }
    Ответ написан
    2 комментария
  • Как одновременно вывести звук на два устройства?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Если все устройства подключены к одному гнезду, то видимо достаточно просто воспроизвести звук, любым удобным способом.

    new System.Media.SoundPlayer(@"c:\filename.wav").Play();

    Более сложные вещи можно сделать, например, с помощью NAudio.

    var searcher = new System.Management.ManagementObjectSearcher("SELECT * FROM Win32_SoundDevice");
    var devices = searcher.Get();
    foreach (var device in devices) 
    {
      Console.WriteLine(device.GetPropertyValue("Caption").ToString());
    }
    
    // ...
    
    var waveReader = new NAudio.Wave.WaveFileReader(fileName);
    var waveOut = new NAudio.Wave.WaveOut();
    waveOut.DeviceNumber = deviceNumber;
    
    var output = new NAudio.Wave.DirectSoundOut();
    output = waveOut;
    output.Init(waveReader);
    output.Play();
    Ответ написан
    Комментировать
  • Спецификации именованного аргумента должны появляться во всех указанных фикс.аргументах. В чем ошибка?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    // добавить chest
    Combin2(n: 4, k: 2, chest: ref chest);
    // либо не указывать имена
    // Combin2(4, 2, ref chest);
    Ответ написан
    1 комментарий
  • Как обработать ответ telegram bot?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Бот должен записать куда-нибудь (например в базу), что ожидается от пользователя.

    В зависимости от реализации, можно сделать ожидание ответа в отдельном потоке. Т.е. бот отправляет клиенту вопрос и приостанавливает выполнение потока, ожидая ответ от клиента. Но в любом случае желательно сохранять информацию в базу данных.

    Также следует учитывать, что пользователь может не прислать ответ. В таком случае нужно ограничить срок ожидания ответа (учитывать дату начала ожидания и проверять дату ответа пользователя).

    Пример:
    Пользователь: Привет!
    Бот: Привет, %username%! Чем я могу помочь? 
    // предполагается, что следующий ответ пользователя будет на вопрос, "чем я могу помочь?"
    // записываем в базу отметку для текущего conversationId, например ставим next=1
    Пользователь: Как обработать ответ telegram bot? 
    // бот смотрит в базе, что поле next равно 1, значит нужно найти ответ на вопрос пользователя
    Бот:  Секундочку, сейчас поищу на Toster...
    Бот: Посмотри здесь: https://toster.ru/q/540828#answer_1235905
    Пользователь: Спасибо!
    Бот:  Без проблем, обращайся!
    Пользователь: Хочу купить билет в Испанию!
    Бот:  Отлично! В какой город?
    // next=2
    Пользователь: Мадрид
    // if (next == 2) { это имя города, проверить название города по базе, если город найден }
    Бот: На какую дату?
    // next=3
    Пользователь: 25.06.2018
    // if (next == 3) { это дата, проверить правильность указания даты, если все правильно }
    Бот: Отлично! Сейчас что-нибудь подберу...
    ...
    Ответ написан
    Комментировать
  • Linq to DataTable как получить строку с минимальным значением в столбце?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Значения NULL уровня базы данных нужно проверять с DBNull.Value.

    Если цены хранятся в виде строк, то следует учитывать, что в разных культурах может использоваться разный десятичный разделитель. Лучше хранить данные сразу в виде числе, чтобы не было проблем с преобразованием форматов, и код работал быстрее.

    "Цена" в представленном коде является просто строкой, содержащей слово "Цена". Если это имя поля, то следует обращаться к нему через myRow.

    from myRow in dt.AsEnumerable()
    where myRow["Цена"] != DBNull.Value
    orderby double.Parse(myRow["Цена"])
    select myRow;
    Ответ написан
    3 комментария
  • Калькулятор на mvc с историей операций?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Если для веб и именно на ASP.NET, то можно:

    1. Реализовать структуру или класс для хранения элемента данных (истории) и использовать статический класс, свойство или поле (например, на уровне класса контроллера) для всей истории:

    public class HistoryItem 
    {
    
      public double X { get; set; }
    
      public double Y { get; set; }
    
      public string Operation { get; set; }
    
      // предполагается, что журнал подразумевает хранение истории вычислений,
      // и хотя можно повторно провести вычисления, в журнале такого по идее быть не должно,
      public double Result { get; set; }
    
    }
    
    // ...
    
    public static List<HistoryItem> History = new List<HistoryItem>();
    
    // ...
    
    History.Add(new HistoryItem { X = 123, Y = 456, Operation = "+", Result =  579 });
    History.Add(new HistoryItem { X = 5, Y = 5, Operation = "*", Result = 25 });

    или проще, без HistoryItem, записывать в виде строк:

    public static List<string> History = new List<string>();
    
    // ...
    
    History.Add("2 * 2 = 4");
    History.Add("3 + 4 = 7");

    Можно сделать поправку на многопоточность и использовать что-нибудь потокобезопасное:

    using System.Collections.Concurrent;
    
    // ...
    
    public static ConcurrentBag<string> History = new ConcurrentBag<string>();
    
    // ...
    
    History.Add("123 + 345 = 468");
    History.Add("7 * 7 = 49");

    Но при такой реализации, история будет доступна только в рамках жизненного цикла приложения.

    2. Записывать в текстовой файл:

    // добавить
    System.IO.File.AppendText("history.log", "5 * 5 = 25");
    // прочитать историю
    // System.IO.File.ReadAllText("history.log");

    При такой реализации, файл истории будет доступен в рамках жизненного цикла устройства хранения данных, пока последняя резервная копия не будет утрачена :-)

    3. Записывать в базу данных.

    Примерно такой же вариант, как и с записью в файл, но более сложный.

    ---

    Если условия задачи позволяют, я бы наверное сделал на стороне клиента (JavaScript) и использовал localStorage:

    var historyData = window.localStorage.getItem('history');
    var history = historyData ? JSON.parse(historyData) : [];
    
    history.push('1 + 1 = 2');
    history.push('2 + 2 = 4');
    history.push('4 + 4 = 8');
    
    window.localStorage.setItem('history', JSON.stringify(history));
    Ответ написан
    Комментировать
  • Как удачно распарсить огромный файл .csv?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Если данных много и их нужно просто добавить (INSERT INTO), то забыть про Entity Framework и использовать SqlBulkCopy.

    Также следует подумать об уменьшении числа столбцов, 617 - это многовато :-)

    Типы придется руками делать, если в CSV не содержится никакой информации о типе данных (например, в заголовке таблицы). Как вариант, можно попробовать определить тип данных автоматически по первой строке данных. Например, если в поле только числа, то считать, что это int (\d+), если числа и есть разделитель, то float ([\d\,\.]+), если дата (\d{1,2}\.\d{1,2}\.\d{2,4}), то datetime (или date), если true или false (true|false), то bool (bit), а по умолчанию varchar. В скобках указан примерный вариант шаблонов регулярных выражения для проверки.
    Ответ написан
    Комментировать