Ответы пользователя по тегу C#
  • Как визуально разделить форму (окно) на части(блоки) в WindowsForms?

    FoggyFinder
    @FoggyFinder
    Используйте Layout-s, в вашем случае должен подойти TableLayoutPanel, который позволяет компоновать элементы управления в виде таблицы.

    Простой пример на русском языке можно найти тут:

    TableLayoutPanel
    Ответ написан
    Комментировать
  • Как предугадать рандом по тикам?

    FoggyFinder
    @FoggyFinder
    Если использовать конструктор по умолчанию класса Random, то в качестве зерна будет использоваться Environment.TickCount - время прошедшее с момента загрузки системы в миллисекундах.

    Для того, чтобы генерировать одну и ту-же последовательность есть отдельная перегрузка, которая принимает "зерно" - значение которое используется для выбора начального числа. Например, вы хотите использовать определенное время

    var ts = new TimeSpan(10, 10, 10);
    var rnd = new Random((int)ts.TotalMilliseconds);


    Таким образом будет генерироваться одна и та-же последовательность.

    for (int i = 0; i < 1; i++)
        Console.WriteLine("{0,4}", rnd.Next(50, 501)); // 265


    Еще можно заглянуть в исходники (Random.cs) и узнать реализацию чтобы "предсказание" было совсем точным :-)
    Ответ написан
    Комментировать
  • Почему консоль выводит первое ведённое число?

    FoggyFinder
    @FoggyFinder
    Как уже написали в других ответах, вам выводит вначале первое число, так как вы именно это и делаете сразу после считывания:

    x = int.Parse(Console.ReadLine());
    y = int.Parse(Console.ReadLine());
    //z = int.Parse(Console.ReadLine());
    Console.WriteLine(x);


    Но, подозреваю, что на самом деле вы спрашиваете о том, почему не выводит само число, а только букву:

    Console.WriteLine("X", x);

    Console.WriteLine ожидает увидеть в качестве первого параметра форматную строку:

    Console.WriteLine("X: {0}", x);

    или через интернирование строк:

    Console.WriteLine($"Y: {y}", y);

    На всякий случай приведу весь код с небольшими изменениями (убрал лишнее):

    int x = int.Parse(Console.ReadLine());
    int y = int.Parse(Console.ReadLine());
    if (x > y)
        Console.WriteLine("X: {0}", x);
    else
        Console.WriteLine($"Y: {y}", y);


    Дополнительно о форматировании строк можно прочитать в документации
    Ответ написан
    Комментировать
  • Как делать расчет по формулам?

    FoggyFinder
    @FoggyFinder
    Можно использовать готовые библиотеки.
    Например, MathNet.Symbolics

    Библиотека написана на F#, но вы можете использовать ее и в C# проекте:

    Math-NET-Symbolics-with-C-VB-NET-and-C-CLI

    Как видно из примера:

    using MathNet.Symbolics;
    using Expr = MathNet.Symbolics.SymbolicExpression;
    ...
    Expr.Parse("1/(a*b");  // выбросит исключение
    Expr.Parse("1/(a*b)").ToString(); // вернет строку "1/(a*b)"


    API достаточно удобное.

    С простыми функциями / формулами проблем быть не должно. Если возможностей будет не хватать или вы найдете баг - открывайте ишшью (на английском языке) или даже PR - мейнтейнер принимает их без проблем.

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

    Есть и другие библиотеки, некоторые по возможностям превосходят MathNet.Symbolics, но так как я с ними не работал, то рекомендовать не могу.
    Ответ написан
    1 комментарий
  • Как вывести оценки в программе С#?

    FoggyFinder
    @FoggyFinder
    Не совсем понятно что именно вызвало затруднения. Но давайте разбираться.

    1. У вас уже есть определение метода ToString для вашего объекта Student. Предлагаю его немного изменить - вместо передачи переменной, указывающей на запрос информации в подробном или сокращенном виде, разделим на два отдельных метода. ShortFormat , который вернет короткий вариант, тогда как переопределение стандартного ToString() для получения полных данных.

    public string ShortFormat()
    {
        return string.Format("{0,15} {1} {2}", Name, BirthDay.ToShortDateString(), GroupName);
    }
    
    public override string ToString()
    {
        StringBuilder sb = new StringBuilder(ShortFormat());
        sb.AppendLine("\nОценки:");
        foreach (var m in Marks)
            sb.AppendFormat("{0} - {1}\n", m.Key, m.Value);
        return sb.ToString();
    }


    2. Для определения есть ли у нашего студента задолженности воспользуемся методом ContainsValue :

    public bool HasDebt => Marks.ContainsValue(2);

    Теперь остается только правильно вызывать методы/свойства:

    switch (menu)
    {
        case 1:
            foreach (var student in students)
                Console.WriteLine(student);
            break;
        case 2:
            foreach (var student in students.Where(s => s.HasDebt))
                Console.WriteLine(student.ShortFormat());
            break;
    }


    Обратите внимание, что для фильтрации должников мы использовали Linq-метод Where.

    И в дополнение несколько комментариев:

    1. Выставлять наружу изменяемую коллекцию (в вашем случае Dictionary<_,_>) обычно не слишком хорошая идея, лучше добавить несколько вспомогательных методов/свойств, которые будут работать с приватным полем.

    2. В текущей реализации меню позволяет выбрать только одну опцию.
    Ответ написан
    Комментировать
  • Как выделить ячейку на ПКМ в DataGridView?

    FoggyFinder
    @FoggyFinder
    Один из вариантов:

    private void dataGridView1_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
    {
        if (e.Button == MouseButtons.Right)
        {
            dataGridView1.ClearSelection();
            dataGridView1[e.ColumnIndex, e.RowIndex].Selected = true;
        }
    }
    Ответ написан
    Комментировать
  • Правильна ли логика копирования массива?

    FoggyFinder
    @FoggyFinder
    Если вам нужно сохранить порядок элементов, то просто воспользуйтесь готовым методом Array.Copy:

    Array.Copy(numbs, numbs2, numbs.Length);

    В противном случае, можно использовать циклы.

    for (int i = 0, z = 0; i < numbs2.GetLength(0); i++)
    {
        for (int j = 0; j < numbs2.GetLength(1); j++)
        {
            numbs2[i, j] = numbs[j, i];
            Console.Write(numbs2[i, j] + " ");
        }
    Console.WriteLine();
    }
    Ответ написан
  • Как правильно сделать функцию для повторяющихся действий?

    FoggyFinder
    @FoggyFinder
    Попробуйте рассматривать функцию в программировании как некоторый участок кода который выполняет определенное действие.

    Давайте разберем на примере вашего задания:

    Заданы три функции y1=x^3, y2=x^3+1, y3= 1/(1+x^2). Определить, являются ли эти функции четными или нечетными.


    Вас может смущать число "три" в формулировке, отбросьте его как не существенное, тогда будет проще понять как правильно поступить. Переформулируем, оставив только самую суть:

    Определить четность функций.


    Возьмем определение "четности":

    Нечётными и чётными называются функции, обладающие симметрией относительно изменения знака аргумента.


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

    Определим тип функции в виде перечисления:

    public enum FuncType { Odd, Even, Unknown };

    Нам понадобиться функция которая будет определять тип функции для конкретной точки:

    Func<double, FuncType> isEven = v =>
    {
        var y1 = func(v);
        var y2 = func(-v);
    
        if (y1 == y2)
            return FuncType.Even;
        if (y1 == -y2)
            return FuncType.Odd;
    
        return FuncType.Unknown;
    };


    и функция для суммирования двух состояний:

    Func<FuncType, FuncType, FuncType> add = (v1, v2) =>
    {
        if (v1 == v2) return v2;
        return FuncType.Unknown;
    };


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

    Для начала нужно определить "состояние" функции для первой точки (a) и, если, однозначного ответа нет, то можно возвращать результат - в дальнейших вычислениях нет необходимости:

    var funcType = isEven(a);
    if (funcType == FuncType.Unknown)
        return FuncType.Unknown;


    теперь, когда предварительная обработка сделана, можно писать цикл:

    for (double x = a + step; x <= b; x += step)
        {
            var funcTypeNext = isEven(x);
            funcType = add(funcType, funcTypeNext);
            if (funcType == FuncType.Unknown)
                return FuncType.Unknown;
         }


    и в итоге нужно вернуть funcType.

    Полностью функция выглядит так:

    public static FuncType IsEvenFunction(Func<double, double> func, double a, double b, double step)
    {
    
        Func<double, FuncType> isEven = v =>
        {
            var y1 = func(v);
            var y2 = func(-v);
    
            if (y1 == y2)
                return FuncType.Even;
            if (y1 == -y2)
                return FuncType.Odd;
    
            return FuncType.Unknown;
        };
    
        Func<FuncType, FuncType, FuncType> add = (v1, v2) =>
        {
            if (v1 == v2) return v2;
            return FuncType.Unknown;
        };
    
        var funcType = isEven(a);
        if (funcType == FuncType.Unknown)
            return FuncType.Unknown;
    
        for (double x = a + step; x <= b; x += step)
        {
            var funcTypeNext = isEven(x);
            funcType = add(funcType, funcTypeNext);
            if (funcType == FuncType.Unknown)
                return FuncType.Unknown;
        }
    
        return funcType;
    }


    Проверка:

    Func<double, double> fn1 = x => x * x * x;
    Func<double, double> fn2 = x => x * x * x + 1;
    Func<double, double> fn3 = x => 1 / (1 + x * x);
    
    Console.WriteLine("Fn1: {0}", IsEvenFunction(fn1, 1, 10, 0.01));
    Console.WriteLine("Fn2: {0}", IsEvenFunction(fn2, 1, 10, 0.01));
    Console.WriteLine("Fn3: {0}", IsEvenFunction(fn3, 1, 10, 0.01));


    Теперь что касается вывода как у вас примере, попробуйте добавить функцию .ToString() для форматирования перечисления. А также добавить описание для функции. Можно использовать кортеж - (описание, функция).

    Если возникнут вопросы - не стесняйтесь спрашивать, буду рад помочь.
    Ответ написан
    1 комментарий
  • Удаление элемента в List C#?

    FoggyFinder
    @FoggyFinder
    Можно использовать метод RemoveAll для удаления всех вхождений удовлетворяющих передаваемому предикату:

    public static void ClearPayment()
    {
        Console.Write("Введите код: ");
        int C = int.Parse(Console.ReadLine());
        if (payments.RemoveAll(p => p.Code == C) > 0)
            Console.WriteLine("Указанный платеж удален ");
        else
            Console.WriteLine("Платежа с таким кодом не существует");
    }


    RemoveAll вернет количество элементов, которые были удалены из списка.

    Еще один способ - использовать комбинацию методов из группы Find и Remove:

    FindIndex + RemoveAt

    или

    Find + Remove

    Отличие от Exists в том, что эти методы возвращают индекс (FindIndex) или сам элемент (Find), а не только проверяют существование подходящего элемента.
    Ответ написан
    Комментировать
  • Ошибка в использовании коллекций в c#?

    FoggyFinder
    @FoggyFinder
    Тут у вас сразу несколько ошибок:

    1. Метод new_list не принадлежит к какому-то определенному типу. Подозреваю, он должен находится в классе Program
    2. Для метода new_list не указан тип возвращаемого значения. Подозреваю, вы хотите чтобы метод возвращал Payment. В таком случае лучше переименовать на ReadPayment:

    public static Payment ReadPayment()
    {
        Console.Write("Введите марку бензина: ");
        int another_petrol = int.Parse(Console.ReadLine());
        Console.Write("Введите количество бензина в литрах: ");
        double another_count = double.Parse(Console.ReadLine());
        Console.Write("Введите номер колонки: ");
        byte another_column = byte.Parse(Console.ReadLine());
        Console.Write("Введите дату: ");
        byte another_code = byte.Parse(Console.ReadLine());
        Console.Write("Введите код: ");
        DateTime another_dt = DateTime.Parse(Console.ReadLine());
        return 
            new Payment(another_column, another_dt, another_petrol, another_count, another_code);
    }


    3. В методе Menu() вызов new_list() ничего не делает, полагаю, вы хотели добавить новый элемент в список:

    case '3':
        payments.Add(ReadPayment());
        break;


    На всякий случай приведу весь код:

    struct Payment
    {
        public int Petrol;
        public double Count;
        public DateTime Dt;
        public byte Column;
        public byte Code;
        public Payment(byte column, DateTime dt, int petrol, double count, byte code)
        {
            Column = column;
            Petrol = petrol;
            Count = count;
            Dt = dt;
            Code = code;
        }
    
        public String SString()
        {
            return String.Format("Колонка: {0} \n" +
                "Дата:  {1}.{2}.{3} {4}:{5}:{6} \n" +
                "Марка бензина: {7} \n" +
                "Количество: {8} \n" +
                "Код платежа: {9}" +
                "\n===============================", Column, Dt.Year, Dt.Month, Dt.Day, Dt.Hour, Dt.Minute, Dt.Second, Petrol, Count, Code);
        }
    }
    class Program
    {
        public static Payment ReadPayment()
        {
            Console.Write("Введите марку бензина: ");
            int another_petrol = int.Parse(Console.ReadLine());
            Console.Write("Введите количество бензина в литрах: ");
            double another_count = double.Parse(Console.ReadLine());
            Console.Write("Введите номер колонки: ");
            byte another_column = byte.Parse(Console.ReadLine());
            Console.Write("Введите дату: ");
            byte another_code = byte.Parse(Console.ReadLine());
            Console.Write("Введите код: ");
            DateTime another_dt = DateTime.Parse(Console.ReadLine());
            return
                new Payment(another_column, another_dt, another_petrol, another_count, another_code);
        }
        public static List<Payment> payments = new List<Payment>();
        public static void Menu()
        {
            Console.WriteLine("1. История платежей");
            Console.WriteLine("2. Редактировать историю платежей");
            Console.WriteLine("3. Добавить новый платеж");
            Console.WriteLine("4. Удалить платеж из списка");
            Console.WriteLine("5. Поиск платежа по коду");
            Console.WriteLine("6. Выход из программы");
            Console.Write("\n \nВведите номер пункта меню: ");
            char M = char.Parse(Console.ReadLine());
    
            switch (M)
            {
                case '1': break; // вывод списка платежей
                case '2': break;
                case '3':
                    payments.Add(ReadPayment());
                    break;
                case '4':
                    Console.WriteLine();
                    break;
                case '5': break;
                case '6': break;
            }
        }
        public static void Main(string[] args)
        {
            Menu();
            Payment np = new Payment(1, new DateTime(2000, 12, 13, 15, 12, 31), 92, 5.12, 001);
            payments.Add(np);
            payments.Add(new Payment(1, new DateTime(2012, 2, 12, 12, 42, 21), 92, 5.13, 001));
            foreach (Payment n in payments)
                Console.WriteLine(np.SString());
        }
    }


    Несколько комментариев:

    1. Вместо метода SString можно переопределять стандартный метод .ToString()
    2. Отклик на ввод пользователя лучше вынести из метода Menu, оставив там только саму печать на консоль.
    3. Структуру лучше делать неизменяемой в явном виде через readonly
    Ответ написан
    Комментировать
  • Как привязать данные таблицы к Combobox?

    FoggyFinder
    @FoggyFinder
    Все правильно, хотя, возможно, вам больше по душе придется стандартный ComboBox, а не
    DataGridComboBoxColumn:

    <DataGridTemplateColumn Header="Должность">
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <ComboBox
                     HorizontalContentAlignment="Center"
                     ItemsSource="{Binding DataContext.Titles, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
                     SelectedItem="{Binding Title}" />
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>


    Будьте внимательны, в примере выше предполагается, что
    коллекция Titles находится на том же уровне (классе), что и коллекция Employee.
    Ответ написан
    Комментировать
  • Почему чат-бот не читает пробелы в БД?

    FoggyFinder
    @FoggyFinder
    Проблема не в наличии пробельного символа в фразе вопроса, а в символе ?.

    В методе поиска соответствующего слова Ans вы удаляете из вопроса все вхождения следующих символов:

    ")(:^^=!?"

    Один из которых встречается в ключевой фразе "Как дела?".

    На данном этапе, вы можете делать аналогичное "удаление" символов для каждого вопроса из списка слов:

    if (q == Trim(baza[i], tr.ToCharArray()))

    Кроме этого оставлю несколько комментариев по коду:

    1. В методе Ans вы каждый раз считываете значения из файла по новой. На данном этапе лучше вынести получение данных в отдельный метод.
    2. Для хранения пары "ключ-значение" отлично подойдет структура данных [Словарь](https://docs.microsoft.com/en-us/dotnet/api/system...
    Ответ написан
    Комментировать
  • Почему в консоли не отображается ноль при значении переменной double менее 1?

    FoggyFinder
    @FoggyFinder
    Символ "#" в форматированной строке не отображает "незначащие" нули.

    В вашем случае, вероятно, подойдет спецификатор "0".

    Подробнее о форматировании чисел можно прочесть, например, в специальном разделе документации:

    Строки настраиваемых числовых форматов

    Позволю себе оставить пару комментариев-советов по поводу кода. Хотел оформить в виде комментария, но в виду объема и того что по каким-то причинам не подсвечивался синтаксис переношу сюда:

    1. Как вы должно быть заметили некоторая функциональность при считывании информации с консоли дублируется. Вместо того чтобы заниматься копированием однотипного участка внося минимальные изменения такие части удобнее выносить в отдельные функции.

    Например:

    public static double ReadDouble
        (string msg = "", string errMsg = "Произошла ошибка, повторите ввод")
    {
        if (!string.IsNullOrWhiteSpace(msg))
            Console.WriteLine(msg);
    
        double value;
        while (!double.TryParse(Console.ReadLine(), out value))
            Console.WriteLine(errMsg);
    
        return value;
    }


    Тогда считывание будет намного понятнее:

    var s = ReadDouble("Введи сечение кабеля, мм2: ");
    var l = ReadDouble("Введи длину кабеля, мм2: ");
    var i = ReadDouble("Введи нагрузку на конце линии, А: ");
    var u = ReadDouble("Введи значение напряжения источника, В: ");


    2. По возможности следует избегать использования "магических чисел" (как у вас - 0.018). Константы должны быть определены как константы. Вместо определения Pi как 3.1415926535 используете встроенное Math.PI.

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

    public double S { get; set; }
    public double L { get; set; }
    public double I { get; set; }
    public double U { get; set; }
    
    public Technocalc(double s, double l, double i, double u)
    {
        S = s;
        L = l;
        I = i;
        U = u;
    }


    4. Методы можно упростить с более современным синтаксисом:

    public double padU => R * I;
    public double R => RConst / S * L * 2;
    public double diameter => Math.PI * S * S / 4;


    Итого, с учетом написанного выше класс будет выглядеть вот так:

    class Technocalc
        {
            public const double RConst = 0.018;
    
            public double S { get; set; }
            public double L { get; set; }
            public double I { get; set; }
            public double U { get; set; }
    
            public Technocalc(double s, double l, double i, double u)
            {
                S = s;
                L = l;
                I = i;
                U = u;
            }
    
            public double padU => R * I;
            public double R => RConst / S * L * 2;
            public double diameter => Math.PI * S * S / 4;
        }



    и вызывающий код:

    public static double ReadDouble
                (string msg = "", string errMsg = "Произошла ошибка, повторите ввод")
            {
                if (!string.IsNullOrWhiteSpace(msg))
                    Console.WriteLine(msg);
    
                double value;
                while (!double.TryParse(Console.ReadLine(), out value))
                    Console.WriteLine(errMsg);
    
                return value;
            }
            public static void Main(string[] args)
            {
                Console.WriteLine("\t\t\t\t" + "Программа расчета падения напряжения в кабеле. 2019 г. Версия 0.0.1");
                var s = ReadDouble("Введи сечение кабеля, мм2: ");
                var l = ReadDouble("Введи длину кабеля, мм2: ");
                var i = ReadDouble("Введи нагрузку на конце линии, А: ");
                var u = ReadDouble("Введи значение напряжения источника, В: ");
                Technocalc cable = new Technocalc(s, l, i, u);
    
                //вывод всей информации на экран
                Console.WriteLine();
                Console.WriteLine("\t\t\t\t" + "Параметры линии:");
                Console.WriteLine("--------------------------------------------------------------------------------");
                Console.WriteLine("Кол-во жил\t\tRкабеля, Ом\t\tСечение, мм2\t\tНапряжение,В\tВых. напряжение, В");
                Console.WriteLine("{0:#0.##}\t\t\t{1:0.0#}\t\t\t{2:0.##}\t\t\t{3:0.##}\t\t{4:0.##}", 2, cable.R, cable.S, cable.U, cable.U - cable.padU);
                Console.WriteLine("--------------------------------------------------------------------------------");
                Console.WriteLine("Rжилы , Ом\t\tДлина кабеля,м\t\tНагрузка, А\t\tПадение U, В\tДиаметр жилы, мм");
                Console.WriteLine("{0:#0.##}\t\t\t{1:#0.##}\t\t\t{2:#0.##}\t\t\t{3:#0.##}\t\t{4:#0.##}\t\t", cable.R / 2, cable.L, cable.I, cable.padU, cable.diameter);
                Console.WriteLine();
                Console.ReadKey(true);
            }
    Ответ написан
    4 комментария
  • Почему не добавляет элемент в список?

    FoggyFinder
    @FoggyFinder
    Как уже правильно указали, проблема состоит в том, что вы каждый раз создаете новый экземпляр ManagerMeeting:

    public void Route(string answer)
    {
        var manager = new ManagerMeeting();


    Также оставлю несколько комментариев по поводу кода:

    1. Наследование применяете неправильно.

    2. Если в сеттерах свойств нет дополнительной проверки на корректность значений полей, то лучше использовать авто-свойства.

    3. Слишком сложная структура - классы Menu, Route кажутся избыточными. Для таких простых сценариев методы перечисленных классов проще перенести в Program.

    4. Класс ManagerMeeting слишком сильно связан с консолью, кроме того есть зависимость от Menu. Если хотите предоставить методы для управления коллекцией (список встреч), то выставите необходимые методы и уже работайте с ними.

    5. Для форматированного вывода собственных классов удобно переопределить метод .ToString()

    Немного переписанные классы с учетом указанного выше:

    class Meetings // Класс встреч
        {
            public string DateMeeting { get; set; }
            public string StartMeeting { get; set; }
            public string EndMeeting { get; set; }
    
            public override string ToString()
            {
                return $"Дата встречи: {DateMeeting}, Начало встречи: {StartMeeting}, Конец встречи: {EndMeeting}";
            }
        }
    
        class ManagerMeeting //  Класс управление встречами
        {
            public List<Meetings> MeetingList { get; } = new List<Meetings>();
            public void Add(Meetings meet)
            {
                MeetingList.Add(meet);
            }
            public string FormatMeetings()
            {
                StringWriter sw = new StringWriter();
                foreach (var meet in MeetingList)
                    sw.WriteLine(meet);
                return sw.ToString();
            }  
        }


    меню:

    class Program
        {
            static ManagerMeeting manager = new ManagerMeeting();
            public static void ShowMainMenu()
            {
                Console.WriteLine("Выберите действие: \n1. Показать все встречи\n2. Создать новую встречу");
            }
    
            public static bool Handler()
            {
                Console.Clear();
                ShowMainMenu();
                string answer = Console.ReadLine();
                switch (answer)
                {
                    case "1":
                        var result = manager.FormatMeetings();
                        if (string.IsNullOrWhiteSpace(result))
                            Console.WriteLine("Список пуск");
                        else
                            Console.WriteLine(manager.FormatMeetings());
                        return true;
                    case "2":
                        manager.Add(ReadMeeting());
                        return true;
                    default:
                        return false;
                }
            }
    
            public static void Main(string[] args)
            {
                while (Handler()) Console.ReadKey(true);
                Console.ReadKey(true);
            }
    
            public static Meetings ReadMeeting()
            {
                Console.WriteLine("Введите дату встречи:");
                var date = Console.ReadLine();
                Console.WriteLine("Введите время начала встречи:");
                var startMeeting = Console.ReadLine();
                Console.WriteLine("Введите время конца встречи:");
                var endMeeting = Console.ReadLine();
    
                Console.WriteLine("Встреча добавлена! \n ");
                //Для проверки, записываются ли поля - записываются
                Console.WriteLine(date + startMeeting + endMeeting);
                return new Meetings
                {
                    DateMeeting = date,
                    StartMeeting = startMeeting,
                    EndMeeting = endMeeting
                };
            }
        }


    Конечно, код выше тоже далек от идеального (всегда есть что улучшать). Например,:

    Предусмотрите проверку данных:

    В считывания информации с консоли:
    * используйте типы данных которые лучше всего подходят для описания свойств (DateTime для даты и времени вместо универсального string)
    * напишите вспомогательные методы GetInteger, GetDateTime и другие которые будут возвращать результат только после того как пользователь ввел корректные данные.

    В классе ManagerMeeting:

    * Пусть вместо void метод Add -возвращает bool в зависимости от успешности добавления (например, чтобы предусмотреть сценарии добавления давно прошедшей встречей).

    И так далее.
    Ответ написан
    2 комментария
  • Можно ли на WPF создавать самостоятельные приложения для частного использования?

    FoggyFinder
    @FoggyFinder
    Поняла, да не до конца. Что еще нужно, чтобы сделать цельное приложение


    Все зависит от самого приложения.

    Назовите плиз примеры из жизни для приложений, которые можно написать используя это фреймворк.


    Их очень много. Приведу несколько OpenSource приложений которые использую или использовал раньше:

    Snoop
    ScreenToGif
    MarkdownMonster
    LiteDbExplorer

    Эти приложения могут индивидуально писаться под заказ как сайты к примеру


    Могут и пишутся.
    Ответ написан
    Комментировать
  • C# WPF Графика. Пересечение фигур. Как привести Polygon в Geometry?

    FoggyFinder
    @FoggyFinder
    По сути ваш вопрос содержит два отдельных вопроса:

    1. Как найти пересечение полигонов.
    2. Как преобразовать Polygon к Geometry.

    Отвечаю на второй:

    За определение сложных геометрических фигур отвечает класс PathFigure. Нужно определить начальную точку и последовательность сегментов (в нашем случае - LineSegment)

    var s1 = p1.Points.Skip(1).Select(p => new LineSegment { Point = p } );
    var g1 = new PathFigure(p1.Points.First(), s1, true);


    где p1 - первый полигон.

    Со вторым поступаем аналогично, ну а дальше вы уже знаете

    var path1 = new PathGeometry(new[] { g1 });
    var path2 = new PathGeometry(new[] { g2 });
    
    var path = new Path()
    {
        Data = new CombinedGeometry(GeometryCombineMode.Intersect, path1, path2),
        Fill = Brushes.Green
    };
    Ответ написан
    Комментировать
  • Как привязать данные разного типа к одному элементу управления и выводить в зависимости от определенного условия?

    FoggyFinder
    @FoggyFinder
    Возможно вам подойдут триггеры данных.

    Например, вы хотите отобразить сообщение о том, что нет данных для отображения, если коллекция числовых данных пуста:

    <ListBox ItemsSource="{Binding CurrentData}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding .}" />
            </DataTemplate>
        </ListBox.ItemTemplate>
        <ListBox.Style>
            <Style TargetType="ListBox">
                <Style.Triggers>
                    <Trigger Property="HasItems" Value="False">
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate>
                                    <TextBlock
                                        Margin="5"
                                        HorizontalAlignment="Center"
                                        VerticalAlignment="Center"
                                        FontSize="16"
                                        Text="{Binding StringIfEmpty}" />
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </ListBox.Style>
    </ListBox>
    Ответ написан
    Комментировать