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

    @Namynnuz
    Для того, чтобы код был реюзабелен и поддерживаем, стоит следовать методологии SOLID. Именно это и есть ООП. Точнее, попытка применения ООП-подхода, похожего на оригинальные изыскания теоретиков, в случае откровенно неудачной реализации.
    Ответ написан
    2 комментария
  • Остановить проверку if на время?

    @Namynnuz
    Тебе просто нужно добавить в условие проверки соответствующий тайм-аут. Например, это можно сделать так:
    public class Checker {
        const double _stdDelta = 10.0d;
        Dictionary<string, DateTime> _dictionary = new Dictionary<string, DateTime>();
    
        bool check( string input, double? delta = null ) {
            if ( !_dictionary.ContainsKey( input ) ) {
                _dictionary.Add( input, DateTime.Now );
                return true;
            }
    
            var d = delta.HasValue ? delta.Value : _stdDelta;
    
            if ( ( DateTime.Now - _dictionary[input] ).TotalSeconds > d ) {
                _dictionary[input] = DateTime.Now;
                return true;
            }
    
            return false;
        }
    
        public void CheckConditionByIfs( int condition ) {
            if ( condition > 100 && check( "second_condition", 20.0d ) ) {
                Console.WriteLine( "Second_condition met, custom timeout set." );
            } else if ( condition > 20 && check( "first_condition" ) ) {
                Console.WriteLine( "First_condition met, standard timeout set." );
            } else {
                Console.WriteLine( "Nothing." );
            }
        }
    
        public void CheckConditionBySwitch( int condition ) {
            switch ( condition ) {
                case var _ when condition > 100 && check( "second_condition", 20.0d ):
                    Console.WriteLine( "Second_condition met, custom timeout set." );
                    return;
                case var _ when condition > 20 && check( "first_condition" ):
                    Console.WriteLine( "First_condition met, standard timeout set." );
                    return;
            }
            Console.WriteLine( "Nothing." );
        }
    }

    Пример использования:
    var rnd = new Random();
    var values = new int[] { 10, 15, 20, 25, 30, 35, 40, 50, 60, 70, 80, 100, 150, 200 };
    var c = new Checker();
    int cnd;
    
    while ( true ) {
        cnd = values[rnd.Next( values.Length )];
        Console.WriteLine( cnd );
    
        if ( rnd.Next( 100 ) > 50 )
            c.CheckConditionBySwitch( cnd );
        else
            c.CheckConditionByIfs( cnd );
    
        Thread.Sleep( 1500 );
    }

    Поясню. В C# 7.0 появилось зарождение Pattern Matching'а, который ты можешь наблюдать в CheckConditionBySwitch (в плане логики выполнения он ничем не отличается от CheckConditionByIfs, поэтому они потом выбираются случайно). По выходу C# 8.0 это будет вполне себе полноценный вариант, как в Nemerle, Kotlin или F#, поэтому к switch и его новому синтаксису стоит присмотреться уже сейчас. Вообще, использование Thread.Sleep для таймаута — дурной тон. Он неточен и выдаёт что-то примерно около, когда у системы появятся свободные ресурсы. Гораздо лучше воспользоваться каким-нить TimeSpan, как таймером. Ну да ладно.
    В данном примере условия для разных веток разделяются, путём назначения им по уникальному стринговому ключу текущей даты-времени (ключ может содержать, в принципе, что угодно). После этого для соотв. ключа ты проверяешь, не пришло ли время обновить значение по ключу и вернуть true, для входа в ветку кода. Если у тебя однозначно ограниченные варианты, то, вероятно, стоило бы создать enum, вместо string и проверять\передавать уже его.
    Ответ написан
    Комментировать
  • Переопределение метода через override. Почему не срабатывает?

    @Namynnuz
    Подобного рода наследования приводят к очень хрупкому коду. Именно поэтому ОПП не является моделированием реальности, иначе потом поддерживать эти наркоманские зависимости будет невозможно и любые изменения на любом уровне будут приводить к тому, что где-то что-то постоянно будет отваливаться и чиня в одном месте, мы будем ломать в другом.
    Кроме того, что тебе стоит прочитать хоть какую-то книженцию по шарпею, следует так же изучить принципы SOLID.
    Ответ написан
    Комментировать
  • Как проверить значения переменных в конструкторе?

    @Namynnuz
    Необходимо чтобы при инициализации объекта (т.е. вызове конструктора) метод проверял сумму этих переменных и либо по новой запрашивал значения либо прерывал с ошибкой.

    Зачем?

    Если нужно сделать всё в едином классе, то достаточно написать статический метод и в нём проверять, после чего уже создавать объект. Бросать исключения в конструкторе — плохая идея. Бросать исключения в принципе — идея неплохая, но они все должны быть уловлены блоками try-catch, с записью в лог или ещё куда.
    Если стоит задача написать консольное приложение, который бы инициализировало класс с правильными значениями, то оно может выглядеть, к примеру, так:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    
    namespace Toster.Q561594 {
        public static class Extentions {
            public static string Join<T>( this IEnumerable<T> list, string separator = "," )
                => string.Join( separator, list );
            public static int[] ConvertConsoleInput( this string input, params char[] separators )
                => input.Split( separators, StringSplitOptions.RemoveEmptyEntries )
                            .Select( int.Parse )
                            .ToArray();
        }
    
        public class Triangle {
            public readonly int A;
            public readonly int B;
            public readonly int Y;
    
            public Triangle(int a, int b, int y) {
                A = a; B = b; Y = y;
            }
    
            public static bool IsValidAngles( int a, int b, int y )
                => a > 0 && b > 0 && y > 0 && ( a + b + y ) == 180;
    
            public override string ToString()
                => $"( {nameof( A )}: {A}, {nameof( B )}: {B}, {nameof( Y )}: {Y} )";
        }
    
        class Program {
            static void Main( string[] args ) {
                int[] temp;
    
                while ( true ) {
                    Console.Write( "Enter three valid space separated angles and press Enter: " );
                    try {
                        temp = Console.ReadLine().ConvertConsoleInput( ' ' );
                        if ( temp.Length != 3 )
                            throw new IndexOutOfRangeException($"Incorrect number of angles: {temp.Length}");
                        if ( Triangle.IsValidAngles( temp[0], temp[1], temp[2] ) )
                            break;
                        else
                            throw new InvalidOperationException( $"Incorrect angles: ( {temp.Join( ", " )} )" );
                        
                    } catch ( Exception ex ) {
                        Console.WriteLine( "Error. " + ex.Message + Environment.NewLine );
                    }
                }
    
                var triangle = new Triangle( temp[0], temp[1], temp[2] );
    
                Console.WriteLine( $"Valid triangle object was created: {triangle.ToString()}" );
                Console.ReadLine();
            }
        }
    }

    При работе в консоли это будет выглядеть как-то так:

    Enter three valid space separated angles and press Enter: i'm typing
    Error. Input string was not in a correct format.
    
    Enter three valid space separated angles and press Enter: 1 2 3
    Error. Incorrect angles: ( 1, 2, 3 )
    
    Enter three valid space separated angles and press Enter: 100 10000
    Error. Incorrect number of angles: 2
    
    Enter three valid space separated angles and press Enter:    5  100    75
    Valid triangle object was created: ( A: 5, B: 100, Y: 75 )

    Обрати внимание на статический класс Extentions, статические методы которого имеют у первого аргумента this. Это методы расширений, они позволяют расширять уже имеющиеся классы, как если бы у них существовали эти методы. StringSplitOptions.RemoveEmptyEntries в ConvertConsoleInput отбрасывает получившиеся пустые строки, поэтому вводить можно хоть «__4____152______24___», оно это превратит сначала в string[] { "4", "152", "24" }, а потом распарсит и выдаст int[] { 4, 152, 24 };
    Ответ написан
    Комментировать
  • Как реализовать стек на C#?

    @Namynnuz
    Например, вот так:
    public class SimpleSystemStack<T> where T : struct, IConvertible {
        private readonly int _sizeOfOneElement;
        private T[] _array;
    
        public SimpleSystemStack( int sizeOfOneElement, T[] inputArray = null ) {
            _sizeOfOneElement = sizeOfOneElement;
            if ( inputArray?.Length > 0 ) {
                Length = inputArray.Length;
                _array = inputArray;
            } else {
                Length = 0;
                _array = new T[sizeOfOneElement];
            }
        }
    
        public int Length { get; private set; }
    
        public T Pop() {
            if ( Length > 0 ) {
                Length--;
                return _array[Length];
            }
            throw new IndexOutOfRangeException("Stack is Empty.");
        }
    
        public void Push( T element ) {
            if ( Length >= int.MaxValue )
                throw new IndexOutOfRangeException("Stack overflow.");
            if ( Length >= _array.Length ) {
                var temp = new T[_array.Length * 2];
                Buffer.BlockCopy( _array, 0, temp, 0, Length * _sizeOfOneElement );
                _array = temp;
            }
            _array[Length] = element;
            Length++;        
        }
    }

    Использование:
    var sss = new SimpleSystemStack<int>( sizeof( int ) );
    
    sss.Push( 1 );
    sss.Push( 2 );
    sss.Push( 3 );
    sss.Pop();
    sss.Pop();
    sss.Push( 4 );

    Работает только для primitive types.
    Ответ написан
    Комментировать
  • Как построить изучение С++ после С#?

    @Namynnuz
    Какое-то базовое понимание относительно современной версии крестов на основе знаний о C# позволяет получить C++ Succinctly. Но это просто чтобы не путаться и начать понимать, чем языки друг от друга по своей сути отличаются.
    Ответ написан
    Комментировать