en
Feedback
C#Hive: Projects & Progress | Программирование

C#Hive: Projects & Progress | Программирование

Open in Telegram

Сообщество единомышленников C#: решаем задачи, учимся, развиваемся и общаемся вместе. Советы по работе на фрилансе, готовые проекты, код ревью, рекомендации и исследования. Вопросы/сотрудничество: @tel_phil9

Show more
1 780
Subscribers
No data24 hours
-17 days
-1030 days
Posts Archive
Решение задачи к посту.
public static class AlgEvklidFinder
{
    public static int BySubtract(int A, int B)
    {
        while (A != B)
        {
            if (A > B) A = A - B;
            else B = B - A;
        }

        return A;
    }

    public static int ByDivision(int A, int B)
    {
        while (A != 0 && B != 0)
        {
            if (A > B) A = A % B;
            else B = B % A;
        }

        return A + B;
    }
}
#Задача #Решение #Полезно

🖥 Задача: наибольший общий делитель (⭐️) Написать статический класс, который реализует нахождение наибольшего общего делителя (НОД) между двумя значениями, используя алгоритм Евклида. Требуется выделить два метода реализации алгоритма, которые будут возвращать НОД: методом деления и методом вычитания. Ниже приведены примеры.
AlgEvklidFinder.BySubtract(112, 32);
AlgEvklidFinder.ByDivision(112, 32);
👉 16 👉 16
AlgEvklidFinder.BySubtract(18, 24);
AlgEvklidFinder.ByDivision(18, 24);
👉 6 👉 6
AlgEvklidFinder.BySubtract(150, 1100);
AlgEvklidFinder.ByDivision(150, 1100);
👉 50 👉 50
AlgEvklidFinder.BySubtract(4, 7);
AlgEvklidFinder.ByDivision(4, 7);
👉 1 👉 1
AlgEvklidFinder.BySubtract(48, 18);
AlgEvklidFinder.ByDivision(48, 18);
👉 6 👉 6 Пишите варианты в комментариях. Решение будет сегодня вечером новым постом в канале. #Задача #Lvl1

📈 Обогащаемся знаниями! #Дайджест полезного материала за последнее время. Задачи: ⏺Шейкерная сортировкаСортировка расчёскойИнтерполяционный поискДвоичный (бинарный) поискРефакторинг кодаРешето СундарамаОбъединение целой и дробной Опросы — что будет выведено на экран: ⏺№1№2№3№4№5№6№7№8 Полезное: ⏺Await внутри конструкции lockКонструкция try..catch..finallyNull у значимых типов, оператор ?. и ??Аннотация NotNull или гарантия не пустых значенийАтомарные операции, безопасность потоков и состояние гонкиОтложенные операцииОтложенное и немедленное выполнение LINQРазбор Strategy паттернаПерехват необработанных исключенийПорядок инициализации статических полейПорядок инициализации полей экземпляраHTTP проксирование в Selenium с ChromeDriverExtensions Самые важные хэштеги: #Фриланс #Полезно #Задача #Опрос #LINQ #Проект #НеочевидныеБаги

🖥 Из примера выше, что будет выведено на экран?
Anonymous voting

🖥 ChromeDriverExtensions: HTTP проксирование для Selenium Данная библиотека представляет собой расширение для движка ChromeD
🖥 ChromeDriverExtensions: HTTP проксирование для Selenium Данная библиотека представляет собой расширение для движка ChromeDriver и позволяет добавить HTTP-прокси с аутентификацией (имя пользователя и пароль). Ранее я уже упоминал об отсутствии подключения прокси с аутентификацией для Selenium. Не буду разглагольствовать о необходимости таких функций, поскольку считаю это само собой разумеющимся. Главное, что обсуждаемая библиотека решает этот вопрос. ➡️ Из исходников Сам пакет максимально лаконичен. Он создаёт расширение (плагин) для Гугл Хрома с настройками прокси и интегрирует его в нашу среду. Пример использования:
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Chrome.ChromeDriverExtensions;

var options = new ChromeOptions();
options.AddHttpProxy(host: "", port: 0, userName: "", password: "");

IWebDriver driver = new ChromeDriver(options);
driver.Navigate().GoToUrl("https://2ip.ru");
Дополнительно библиотека сохраняет плагин в рабочей папке, который можно использовать в будущем в качестве уже готового решения:
var options = new ChromeOptions();
options.AddExtension("Plugins\\proxy_auth_plugin_GUID.zip");

IWebDriver driver = new ChromeDriver(options);
driver.Navigate().GoToUrl("https://2ip.ru");
Пакет можно установить с NuGet: OpenQA.Selenium.Chrome.ChromeDriverExtensions. #Полезно #Selenium #ChromeDriverExtensions #Прокси

Из примера выше, что будет выведено на экран?
Anonymous voting

🖥 Порядок инициализации полей экземпляра В прошлый раз мы обсудили порядок инициализации только для статических случаев. Понимание этих правил было важным для ожидания корректных результатов. Сегодня же раз мы рассмотрим детальный обзор правил инициализации для всех случаев. ➡️ Определение порядка Происходит каждый раз при создании нового экземпляра класса:
new MainClass()
В нулевую очередь — назовём это так —, происходит разовая инициализация статических "случаев", что мы обсудили прошлой темой. Если же класс имеет базовый класс, в котором также имеются статические "случаи", то они будут инициализированы первыми: от самого базового типа до текущего класса. В первую очередь, все поля экземпляра получают значения по умолчанию для их типа (0 для int, null для ссылочных типов, false для bool и т.д.). Во вторую очередь, поля, инициализированные непосредственно при объявлении, например:
int x = 10;
Они инициализируются в порядке их объявления в классе. В третью очередь, если класс имеет базовый класс, то сначала выполняются инициализаторы полей экземпляра в базовом классе, согласно приведенному выше порядку. В четвёртую очередь, если класс имеет базовый класс, то выполняется вызов конструктора базового класса. В пятую очередь, после завершения инициализации полей экземпляра и вызова конструктора базового класса выполняется код в конструкторе текущего класса. ➡️ Пример для иллюстрации Рассмотрим порядок всех вызовов с ответом на вопрос «что же будет, если класс является наследником?» и запустим следующий код:
new Main().Method();

class Main : Base
{
    static Main() => Console.WriteLine("4. Инициализация статического конструктора");
    public Main() : this(0) => Console.WriteLine("9. Явно вызванный конструктор");
    public Main(int value) => Console.WriteLine("8. Конструктор, вызванный другим конструктором");

    private static int staticField = Getter("3. Инициализация статических полей");
    private int instanceField = Getter("5. Инициализация нестатических полей");

    public void Method() => Console.WriteLine("10. Выполнение метода");
}

class Base
{
    static Base() => Console.WriteLine("2. Инициализация статического конструктора базового класса");
    public Base() => Console.WriteLine("7. Конструктор базового класса");

    private static int staticField = Getter("1. Инициализация статических полей базового класса");
    private int instanceField = Getter("6. Инициализация нестатических полей базового класса");

    protected static int Getter(string msg)
    {
        Console.WriteLine(msg);
        return 0;
    }
}
Вывод:
1. Инициализация статических полей базового класса
2. Инициализация статического конструктора базового класса
3. Инициализация статических полей
4. Инициализация статического конструктора
5. Инициализация нестатических полей
6. Инициализация нестатических полей базового класса
7. Конструктор базового класса
8. Конструктор, вызванный другим конструктором
9. Явно вызванный конструктор
10. Выполнение метода
То есть явно вызванный конструктор будет выполнен в последнюю очередь, после выполнения других конструкторов, явно не вызванных, в том числе и от базовых классов. При наследовании сначала инициализируются члены базового класса, затем члены производного класса. Сначала выполняются статические конструкторы, а потом конструкторы экземпляров. Понимание этих правил поможет писать более надёжный и предсказуемый код. При разработке сложных классов и иерархий наследования всегда стоит помнить о порядке инициализации и о том, как он влияет на поведение кода. #Полезно #Инициализация

Решение задачи к посту.
public static class LongExtension
{
    public static decimal ConcatWithFractional(this long units, long nano)
    {
        int countDigits = nano == 0 ? 0 : (int)Math.Floor(Math.Log10(Math.Abs(nano)) + 1);
        if (countDigits == 0) return units;

        decimal zeroWithFractional = Math.Abs(nano) / (decimal)Math.Pow(10, countDigits);
        decimal concated = Math.Abs(units) + zeroWithFractional;

        return units < 0 || nano < 0 ? -concated : concated;
    }
}
#Задача #Решение #Полезно #Extensions

🖥 Задача: объединение целой и дробной (⭐️⭐️) Написать метод расширения для типа long, который будет служить объединением целой и дробной части числа, возвращая преобразованный результат в decimal. При этом, аргументы левой и правой части метод должен принимать как long, а решение задачи должно миновать конвертации через string методы. Ниже приведены примеры.
101L.ConcatWithFractional(59);
👉 101,59
(-1231L).ConcatWithFractional(-042)
👉 -1231,42
long units = -89;
long nano = -735;
units.ConcatWithFractional(nano);
👉 -89,735
long.MaxValue.ConcatWithFractional(long.MaxValue);
👉 9223372036854775807,922337204
LongExtension.ConcatWithFractional(units: -09, nano: 101);
👉 -9,101
492L.ConcatWithFractional(650000000);
👉 492,65
0L.ConcatWithFractional(-578400001)
👉 -0,578400001 Пишите варианты в комментариях. Решение будет сегодня вечером новым постом в канале. #Задача #Lvl2

🖥 Порядок инициализации статических полей Порядок инициализации полей и конструкторов класса подчиняется определённым правилам. Понимание этих правил важно для предсказуемого и корректного поведения нашего кода. ➡️ Определение порядка В первую очередь, инициализируются явные статические инициализаторы — это инициализированные поля непосредственно при объявлении, например:
public static int count = 5;
Они инициализируются в порядке их объявления в классе, сверху вниз. Во вторую очередь, инициализируется статический конструктор. Если класс содержит такой конструктор:
static MyClass()
{
    // ...
}
...то он выполняется после инициализации статических полей и перед созданием первого экземпляра класса. ❗️Статический конструктор и статические поля инициализируются единожды, при самом первом обращении к классу: вызов статического метода, создание экземпляра класса, обращение к статическому полю. ➡️ Пример конфликта Когда мы создаём класс, который содержит статические поля, важно инициализировать их в правильном порядке. Рассмотрим следующий код:
Console.WriteLine($"Value1: {Foo.value1}");
Console.WriteLine($"Value2: {Foo.value2}");
Console.WriteLine($"Bar: {Foo.bar}");

class Foo
{
    public static int bar = value1 - value2;
    public static int value1 = 8;
    public static int value2 = 3;
}
На первый взгляд, код кажется правильным. Имеем максимальное значение 8, минимальное 3 и ожидаем, что поле bar будет равняться пяти. Однако, если запустить этот код для вывода значений, то увидим результаты, которые не были ожидаемы:
Value1: 8
Value2: 3
Bar: 0
Исправить это можно просто изменив порядок объявления полей:
class Foo
{
    public static int value1 = 8;
    public static int value2 = 3;
    public static int bar = value1 - value2;
}
Теперь выполнение даёт правильные результаты:
Value1: 8
Value2: 3
Bar: 5
К сожалению, такой подход не создаёт идеального кода, читаемого и поддерживаемого. Вполне возможно, что позднее другой разработчик может изменить порядок полей, чтобы, например, отсортировать их в алфавитном порядке и невольно станет причиной ошибки. Лучше исправить это и установить значения в пределах статического конструктора, как показано ниже:
class Foo
{
    static Foo()
    {
        value1 = 8;
        value2 = 3;
        bar = value1 - value2;
    }

    public static int value1;
    public static int value2;
    public static int bar;
}
➡️ Пример порядка для иллюстрации Чтобы детально увидеть, в каком порядке происходит инициализация, запустим следующий код:
Console.WriteLine("1. Start");
Console.WriteLine($"4. Output: {Foo.a}");

class Foo
{
    static Foo()
    {
        Console.WriteLine("3. Static ctor");
        a = 10;
    }

    public static int a;
    public static int b = SetB(); // Эквивалентно b = 3;

    private static int SetB()
    {
        Console.WriteLine("2. Instance fields");
        return 3;
    }
}
Вывод:
1. Start
2. Instance fields
3. Static ctor
4. Output: 10
Вызываемое поле вообще равняется нулю (по дефолту для int), но, благодаря статическому конструктору, ему было присвоено значение в последнюю очередь до возврата управления в 4 пункт. В таком случае, порядок уже не важен. Главное только не забыть присвоить значение необходимым полям. ➡️ Итог Из примеров выше, думаю, вся картина наглядным образом теперь должна быть понятна. А в связи с результатами последнего опроса, а также и с другим непредсказуемым поведением при проектировании, подобные посты я буду помечать новым хэштегом #НеочевидныеБаги. Он будет сообщать о тех случаях, где мы легко можем словить баг, а его обнаружение будет близко к нервному срыву. Пусть подобные метки научат нас обращать внимание на те детали, которые кажутся незначительными. #Полезно #Инициализация #НеочевидныеБаги

Из примера выше, что будет выведено на экран?
Anonymous voting

#Опрос #НеочевидныеБаги
#Опрос #НеочевидныеБаги

Настоящий мужчина всегда ответит: "ты 0 в моей жизни!" 👌 #Юмор

Решение задачи к посту.
void Sundaram(int n)
{
    if (n < 2) throw new ArgumentOutOfRangeException();

    bool[] marked = Marking(n);
    List<int> primeNumbers = PrimeNumbersFrom(marked);

    Console.WriteLine(string.Join(", ", primeNumbers));
}

bool[] Marking(int n)
{
    int k = (n - 2) / 2;
    bool[] marked = new bool[k + 1];

    for (int i = 1; i <= k; i++)
    {
        for (int j = i; j <= k; j++)
        {
            int number = i + j + 2 * i * j;
            if (number <= k) marked[number] = true;
        }
    }

    return marked;
}

List<int> PrimeNumbersFrom(bool[] marked)
{
    List<int> nums = new() { 2 };

    for (int i = 0; i < marked.Length; i++)
    {
        if (!marked[i])
        {
            int number = 2 * i + 1;
            if (number == 1) continue;
            nums.Add(number);
        }
    }

    return nums;
}
#Задача #Решение #Полезно

🖥 Задача: решето Сундарама (⭐️) Написать метод, принимающий некоторый диапазон чисел N (целочисленное значение), из которого необходимо получить все простые числа до N, используя реализацию решето Сундарама и вывести результат на экран. Ниже приведены примеры.
Sundaram(25);
👉 2, 3, 5, 7, 11, 13, 17, 19, 23
Sundaram(59);
👉 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53
Sundaram(101);
👉 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97
Sundaram(777);
👉 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773 Пишите варианты в комментариях. Решение будет сегодня вечером новым постом в канале. #Задача #Lvl1

🖥 Перехват необработанных исключений Необработанное исключение — это исключение, которое возникает, но не имеет соответствующего обработчика. Если исключение остаётся необработанным, программа аварийно завершает работу с ошибкой. Известно, что для обработки ошибки следует использовать конструкцию try..catch..finally:
try
{
    int value = int.Parse("Здесь мы получим ошибку");
}
catch
{
    Console.WriteLine("Здесь мы её обработаем");
}

Console.WriteLine("Здесь код продолжит свою работу...");
// ...
//
Однако вне такой конструкции приложение будет аварийно завершено. Основной способ обработки иной ситуации является подписка на событие UnhandledException:
AppDomain.CurrentDomain.UnhandledException
Здесь определяется обработчик событий, который вызывается при возникновении необработанного исключения в домене приложения по умолчанию. Подписываемся на событие при старте приложения и проверяем:
AppDomain.CurrentDomain.UnhandledException += UnhandledException;

// Здесь мы получим ошибку
throw new Exception("Test");

Console.WriteLine("Пытаемся продолжить работу...");
// ...
//

void UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
    Console.WriteLine("Необработанная ошибка перехвачена");
}
Вывод будет примерно следующим:
Необработанная ошибка перехвачена
Unhandled exception. System.Exception: Test
   at Program.<Main>$(String[] args)
Примечания: Данная возможность не отменяет падения приложения, но предоставляет сведения об ошибке; Не все исключения можно перехватить. Например, StackOverflowException часто поймать нельзя; Старайтесь вручную завершать работу после отлова необработанного исключения через, например, Environment.Exit(0). ➡️ Важные моменты Не злоупотребляйте перехватом всех исключений. Вместо этого старайтесь использовать блоки try..catch..finally в местах, где ожидаются исключения, чтобы контролировать ход выполнения программы. Перехват всех необработанных исключений следует использовать как крайнюю меру, а не для маскировки ошибок. В обработчиках необработанных исключений обязательно логируйте информацию об исключении (сообщение, стек вызовов и т.п.), чтобы можно было найти и исправить ошибку. После перехвата необработанного исключения приложение должно быть завершено, так как оно находится в некорректном состоянии. #Полезно #Exception #TryCatch

Из примера выше, что будет выведено на экран?
Anonymous voting