C# Cooking
133 subscribers
40 photos
50 videos
66 links
Просветительский канал по языку C# CSharpCooking.github.io
Download Telegram
Вопрос:
Чем отличается C# от Python?
Ответ:
C# и Python – это два популярных языка программирования, но они имеют ряд отличий:
Типизация: C# – язык со строгой типизацией, тогда как Python использует динамическую типизацию. Это означает, что в C# типы переменных должны быть указаны явно и не могут быть изменены после объявления, в то время как в Python типы данных выводятся автоматически и могут изменяться.
Синтаксис: Python известен своим чистым и кратким синтаксисом, который часто использует отступы для структурирования кода. C# имеет более формальный синтаксис, похожий на C++ и Java, и использует фигурные скобки для обозначения блоков кода.
Производительность: C# обычно имеет более высокую производительность по сравнению с Python, особенно в приложениях, где необходимы интенсивные вычисления благодаря тому, что он компилируется в промежуточный байт-код и затем оптимизируется JIT-компилятором.
Платформы и экосистемы: C# тесно интегрирован с платформой .NET и широко используется для разработки Windows-приложений, веб-приложений с использованием ASP.NET и кроссплатформенных мобильных приложений с использованием Xamarin. Python очень популярен в науке о данных, машинном обучении, веб-разработке с использованием фреймворков, таких как Django и Flask, и в автоматизации.
Библиотеки и фреймворки: Python имеет огромное количество библиотек для различных целей, особенно в области науки о данных и машинного обучения. C# также имеет множество библиотек, но они в большей степени сосредоточены на разработке приложений.
Сообщество: сообщество Python традиционно сильно представлено в академических и научных кругах, тогда как C# имеет сильное присутствие в промышленном секторе и среди разработчиков корпоративного программного обеспечения.
Управление памятью: C# использует автоматическое управление памятью с помощью сборщика мусора, как и Python. Однако, C# предоставляет более гибкие возможности для управления ресурсами и памятью через использование конструкций, таких как using и явное освобождение ресурсов с помощью интерфейса IDisposable.
Многопоточность: C# предлагает более развитые средства для многопоточной обработки и параллельного программирования через Task Parallel Library (TPL) и асинхронные методы. В Python, из-за глобальной блокировки интерпретатора (GIL), истинное параллельное выполнение потоков является более сложной задачей, хотя он поддерживает многопроцессорность и асинхронное программирование.
Ошибка и исключения: C# требует явной обработки исключений с использованием конструкции try-catch, тогда как Python позволяет опускать обработку исключений (хотя это считается плохой практикой).
Инструменты разработки: C# тесно интегрирован с Visual Studio, которая является одной из наиболее мощных сред разработки. Python, с другой стороны, можно разрабатывать в различных редакторах кода и IDE, таких как PyCharm, Jupyter Notebooks и Visual Studio Code.
Интероперабельность: C# легко взаимодействует с другими технологиями и языками в экосистеме .NET. Python является более скриптовым языком и может быть использован для автоматизации множества систем и приложений, но может иметь ограничения в интеграции с некоторыми платформами.
В зависимости от контекста и требований проекта, выбор между C# и Python может быть обусловлен различными факторами, такими как производительность, экосистема, предпочтения в синтаксисе и доступные библиотеки.

#программирование #сишарп #csharp #csharpdotnet #csharpprogramming
Вопрос:
Вызов метода GetTypes на многомодульной сборке возвращает все типы из всех модулей . Что понимается под многомодульной сборкой?
Ответ:
Многомодульная сборка в .NET представляет собой сборку, состоящую из нескольких модулей. В контексте .NET, модуль – это единица компиляции, которая может содержать код и метаданные. Модуль похож на сборку, но не может быть развернут самостоятельно; вместо этого он должен существовать внутри сборки. Одномодульные сборки (что является наиболее общим случаем) содержат один модуль, который совпадает с самой сборкой. В многомодульных сборках содержится несколько модулей, объединенных в одну сборку. Создание многомодульных сборок редко используется, но может быть полезным, например, когда вы хотите объединить код, написанный на разных языках программирования, в одну сборку или когда вы хотите разделить большую сборку на более мелкие модули для улучшения управления кодом. Вот пример того, как можно создать многомодульную сборку с использованием компилятора командной строки C# (csc):
# Компилируем первый модуль (без создания сборки)
csc /target:module Module1.cs
# Компилируем второй модуль (без создания сборки)
csc /target:module Module2.cs
# Создаем многомодульную сборку, включающую оба модуля
csc /target:library /out:MultiModuleAssembly.dll /addmodule:Module1.netmodule;Module2.netmodule
При использовании метода GetTypes на многомодульной сборке, метод вернет все типы, определенные во всех модулях, включенных в эту сборку.
Когда говорится, что модуль не может быть развернут самостоятельно, это означает, что он не может существовать как независимая единица развертывания, которую можно было бы загрузить и выполнить непосредственно в среде исполнения .NET. Модули (с расширением .netmodule) содержат скомпилированный код и метаданные, но не содержат сборочную информацию, которая необходима среде исполнения для идентификации, версионности и разрешения зависимостей. Эта информация содержится только на уровне сборки. Сборка, с другой стороны, является единицей развертывания в .NET и содержит всю необходимую информацию для загрузки и выполнения кода средой исполнения. Сборка может содержать один или несколько модулей, и хотя каждый модуль может содержать код, только сборка предоставляет контекст, необходимый для того, чтобы этот код мог быть выполнен. В обычной практике разработчики чаще всего работают с одномодульными сборками, где вся сборка состоит из одного модуля. Многомодульные сборки используются реже и обычно применяются в специализированных сценариях.

#программирование #сишарп #csharp #csharpdotnet #csharpprogramming
Вопрос:
Как задействовать статическое событие TaskScheduler.UnobservedTaskException в сценарии использования задач с необработанными исключениями?
Ответ:
Необработанные исключения в автономных задачах называются необнаруженными исключениями, и среда CLR будет повторно генерировать исключение в потоке финализаторов, когда объект задачи покидает область видимости и обрабатывается сборщиком мусора). TaskScheduler.UnobservedTaskException – это событие, которое срабатывает, когда задача, завершившаяся с исключением, была собрана сборщиком мусора, не будучи обработанной. Это может быть полезно для перехвата и обработки исключений, которые не были явно обработаны в коде.
Ниже пример, который показывает, как можно использовать TaskScheduler.UnobservedTaskException в сценарии с задачами:
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static void Main()
{
// Подписка на событие UnobservedTaskException
TaskScheduler.UnobservedTaskException += (sender, e) =>
{
Console.WriteLine("Необработанное исключение в задаче:");
e.SetObserved(); // Помечаем исключение как обработанное
foreach (var ex in e.Exception.InnerExceptions)
{
Console.WriteLine(" - " + ex.Message);
}
};
// Создание задачи, которая завершается с исключением
var task = Task.Run(() =>
{
throw new Exception("Исключение в задаче");
});
// Задача-продолжение, которая также генерирует исключение
var continuation = task.ContinueWith(t =>
{
throw new Exception("Исключение в продолжении задачи");
});
// Ждем некоторое время, чтобы задачи завершились
Thread.Sleep(1000);
// Выполнение сборки мусора для того, чтобы событие UnobservedTaskException сработало
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("Завершение программы.");
}
}
В этом примере создаются две задачи, обе из которых генерируют исключения. Затем явно вызывается сборка мусора (GC.Collect и GC.WaitForPendingFinalizers), чтобы поток финализаторов вызвал событие TaskScheduler.UnobservedTaskException для исключений, которые не были обработаны.
Для справки:
- Метод GC.Collect явно инициирует процесс сборки мусора. Это означает, что сборщик мусора пытается освободить память, удаляя объекты, которые больше не доступны (т.е. на которые нет ссылок). Обычно не рекомендуется вызывать этот метод вручную, потому что сборщик мусора в .NET достаточно эффективен и оптимизирован для работы в различных сценариях. Однако, в некоторых специальных случаях, когда вы точно знаете, что это может быть полезно (например, перед большими вычислениями), можно использовать явное взаимодействие со сборщиком мусора.
- Метод GC.WaitForPendingFinalizers приостанавливает выполнение текущего потока до тех пор, пока сборщик мусора не завершит выполнение всех финализаторов. Финализатор – это специальный метод, который выполняется перед уничтожением объекта, и обычно используется для освобождения неуправляемых ресурсов. Этот вызов полезен в сценариях, где вам необходимо убедиться, что все финализируемые объекты были очищены перед продолжением выполнения кода. Как и с GC.Collect, это не что-то, что следует делать часто, и должно использоваться с осторожностью.

#программирование #сишарп #csharp #csharpdotnet #csharpprogramming
Мощная особенность продолжений связана с тем, что они запускаются, только когда завершены все дочерние задачи. В этой точке любые исключения, сгенерированные дочерними задачами, маршализируются в продолжение.

В примере на слайде мы начинаем три дочерние задачи, каждая из которых генерирует исключение NullReferenceException. Затем мы перехватываем все исключения сразу через продолжение на родительской задаче.

#программирование #сишарп #csharp #csharpdotnet #csharpprogramming
Расширяющий метод “поглощает” необработанные исключения задачи. Метод может быть улучшен добавлением кода для регистрации исключения.

#программирование #сишарп #csharp #csharpdotnet #csharpprogramming
This media is not supported in your browser
VIEW IN TELEGRAM
Параллелизм задач. Расширяющий метод, продолжение и дочерние задачи.

#программирование #сишарп #csharp #csharpdotnet #csharpprogramming
Важно понимать, что когда продолжение не выполнилось из-за упомянутых флагов, оно не забыто и не отброшено – это продолжение отменено. Например, взгляните на приведенный на втором слайде код. Несложно заметить, что задача t3 всегда будет запланирована – даже если t1 не генерирует исключение. Причина в том, что если задача t1 завершена успешно, тогда задача fault будет отменена, и с учетом отсутствия ограничений продолжения задача t3 будет запущена безусловным образом.

Если нужно, чтобы задача t3 выполнялась, только если действительно была запущена задача fault, то потребуется поступить так:
Task t3 = fault.ContinueWith (ant => Console.WriteLine ("t3"), TaskContinuationOptions.NotOnCanceled);
(В качестве альтернативы мы могли бы указать OnlyOnRanToCompletion; разница в том, что тогда задача t3 не запустилась бы в случае генерации исключения внутри задачи fault.)

#программирование #сишарп #csharp #csharpdotnet #csharpprogramming
С помощью методов ContinueWhenAll и ContinueWhenAny класса TaskFactory выполнение продолжения можно планировать на основе завершения множества предшествующих задач. Однако эти методы стали избыточными после появления комбинаторов задач (WhenAll и WhenAny).

#параллелизмзадач #программирование #сишарп #taskparallelism #csharp #csharpdotnet #csharpprogramming
Вызов ContinueWith более одного раза на той же самой задаче создает множество продолжений на единственном предшественнике. Когда предшественник завершается, все продолжения запускаются вместе (если только не было указано значение TaskContinuationOptions.ExecuteSynchronously, эта опция заставляет продолжения выполняться последовательно в том же потоке, что и предшествующая задача). Код на слайде ожидает одну секунду, а затем выводит на консоль либо 'ABCD', либо 'BACD'.

#параллелизмзадач #программирование #сишарп #taskparallelism #csharp #csharpdotnet #csharpprogramming
Вопрос:
Можно ли назвать лямбда-выражение делегатом?
Ответ:
Лямбда-выражение и делегат – это разные понятия в C#:
– Делегат – это ссылочный тип, который ссылается на метод. Делегат объявляется отдельно с использованием ключевого слова delegate.
– Лямбда-выражение – это анонимный метод, который может быть использован для инициализации делегата. Лямбда объявляется в виде (input params) => {method body}.
Лямбда-выражение не является делегатом, но оно может быть преобразовано в делегат. Когда мы присваиваем лямбду делегату, компилятор автоматически компилирует лямбду в отдельный анонимный метод и создает экземпляр делегата, который ссылается на этот метод. Поэтому строго говоря нельзя утверждать, что "лямбда-выражение – это делегат". Лямбда просто используется для инициализации делегата.

#лямбдавыражение #делегат #программирование #сишарп #lambdaexpression #delegate #csharp #csharpdotnet #csharpprogramming
Вопрос:
Что такое интернирование строк?
Ответ:
Интернирование строк – это процесс сохранения одной копии каждой уникальной строки для уменьшения использования памяти. Этот процесс реализован в .NET Framework с использованием строкового пула интернирования (String Intern Pool).
Когда строка интернируется, проверяется наличие этой строки в пуле интернирования. Если строка уже есть в пуле, возвращается ссылка на строку из пула, а не создается новый экземпляр строки. Если строки нет в пуле, она добавляется туда, и возвращается ссылка на новый экземпляр строки.
Пример:
string str1 = "Hello, World!";
string str2 = string.Intern("Hello, World!");
Console.WriteLine(object.ReferenceEquals(str1, str2)); // Выведет "True"
В этом примере, даже если "Hello, World!" был создан дважды, обе переменные str1 и str2 ссылаются на один и тот же экземпляр строки в памяти благодаря интернированию.
Тем не менее, стоит помнить, что не все строки автоматически интернируются в .NET. Литералы строк в исходном коде автоматически интернируются, но динамически созданные строки – нет, если только вы явно не вызовете метод string.Intern().
Интернирование может быть полезным, когда работают с большим количеством повторяющихся строк, чтобы оптимизировать использование памяти. Однако оно может быть неэффективным при работе со строками, которые редко повторяются.

#интернированиестрок #программирование #сишарп #stringintern #csharp #csharpdotnet #csharpprogramming
Инфраструктура PLINQ, класс Parallel и объекты Task автоматически маршализируют исключения потребителю, то есть исключения автоматически перехватываются и повторно генерируются для вызывающего потока. Но, к сожалению, дело не сводится просто к перехвату DivideByZeroException. Поскольку параллельные библиотеки задействуют множество потоков, вполне возможна одновременная генерация двух и более исключений. Чтобы обеспечить получение сведений обо всех исключениях, по указанной причине исключения помещаются в контейнер AggregateException, свойство InnerExceptions которого содержит каждое из перехваченных исключений.

Как инфраструктура PLINQ, так и класс Parallel при обнаружении первого исключения заканчивают выполнение запроса или цикла, не обрабатывая любые последующие элементы либо итерации тела цикла. Однако до завершения текущей итерации цикла могут быть сгенерированы дополнительные исключения. Первое возникшее исключение в AggregateException доступно через свойство InnerException.

#aggregateexception #параллельноепрограммирование #сишарп #taskfactory #parallelprogramming #csharp #csharpdotnet #csharpprogramming