C# | Вопросы собесов
5.1K subscribers
35 photos
1 file
983 links
Download Telegram
🤔 Что такое медиатор?

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

🚩Примеры использования

1⃣Определение интерфейса медиатора
public interface IMediator
{
void Notify(object sender, string ev);
}


2⃣Реализация медиатора
public class DialogMediator : IMediator
{
private Button _button;
private TextBox _textBox;

public DialogMediator(Button button, TextBox textBox)
{
_button = button;
_button.SetMediator(this);
_textBox = textBox;
_textBox.SetMediator(this);
}

public void Notify(object sender, string ev)
{
if (ev == "ButtonClick")
{
_textBox.Clear();
}
else if (ev == "TextBoxEnter")
{
_button.SetEnabled(true);
}
}
}


3⃣Компоненты, взаимодействующие через медиатора
public class Button
{
private IMediator _mediator;

public void SetMediator(IMediator mediator)
{
_mediator = mediator;
}

public void Click()
{
Console.WriteLine("Button clicked");
_mediator.Notify(this, "ButtonClick");
}

public void SetEnabled(bool enabled)
{
Console.WriteLine($"Button is {(enabled ? "enabled" : "disabled")}");
}
}

public class TextBox
{
private IMediator _mediator;

public void SetMediator(IMediator mediator)
{
_mediator = mediator;
}

public void EnterText()
{
Console.WriteLine("Text entered");
_mediator.Notify(this, "TextBoxEnter");
}

public void Clear()
{
Console.WriteLine("TextBox cleared");
}
}


4⃣Использование медиатора в приложении
var button = new Button();
var textBox = new TextBox();
var mediator = new DialogMediator(button, textBox);

textBox.EnterText(); // Ввод текста активирует кнопку
button.Click(); // Нажатие кнопки очищает текстовое поле


🚩Плюсы и минусы

Снижение связанности
Компоненты не взаимодействуют напрямую, а используют медиатор.
Упрощение поддержки
Вся логика взаимодействия сосредоточена в одном месте.
Повышение модульности
Легко добавлять новые компоненты или изменять существующие.
Усложнение медиатора
Медиатор может стать сложным, если в него добавляется много логики.
Единая точка отказа
Если медиатор выходит из строя, это может повлиять на всю систему.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍31
🤔 Как работает async/await?

async/await — это механизм для асинхронного программирования, позволяющий писать асинхронный код, который выглядит как синхронный. Ключевое слово async указывает, что метод может содержать await, который приостанавливает выполнение до завершения задачи. Во время ожидания поток освобождается для других операций, что повышает производительность. После завершения задачи выполнение метода возобновляется с того же места.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10
🤔 Как в EF испольузем join`ы?

В Entity Framework (EF) join операции используются для объединения данных из нескольких таблиц на основе связанных полей. В EF можно использовать как метод синтаксиса, так и синтаксис запросов (LINQ). Рассмотрим оба подхода на примерах.

🚩Метод синтаксиса (Method Syntax)

Метод синтаксиса предоставляет методы расширения для выполнения join операций. Допустим, у нас есть две сущности: Student и Enrollment, где Enrollment содержит StudentId, который является внешним ключом, связывающим эти две сущности.
public class Student
{
public int StudentId { get; set; }
public string Name { get; set; }
}

public class Enrollment
{
public int EnrollmentId { get; set; }
public int StudentId { get; set; }
public string Course { get; set; }
}


Использование метода синтаксиса
using (var context = new SchoolContext())
{
var query = context.Students
.Join(context.Enrollments,
student => student.StudentId,
enrollment => enrollment.StudentId,
(student, enrollment) => new
{
StudentName = student.Name,
Course = enrollment.Course
})
.ToList();

foreach (var item in query)
{
Console.WriteLine($"Student: {item.StudentName}, Course: {item.Course}");
}
}


🚩Синтаксис запросов (Query Syntax)

Синтаксис запросов использует выражения LINQ, которые похожи на SQL-запросы. Тот же пример с Student и Enrollment, но с использованием синтаксиса запросов.
using (var context = new SchoolContext())
{
var query = (from student in context.Students
join enrollment in context.Enrollments
on student.StudentId equals enrollment.StudentId
select new
{
StudentName = student.Name,
Course = enrollment.Course
}).ToList();

foreach (var item in query)
{
Console.WriteLine($"Student: {item.StudentName}, Course: {item.Course}");
}
}


🚩Типы `join` операций

🟠Inner Join
Соединяет строки из двух таблиц, когда есть совпадения по ключу.
🟠Left Join
Возвращает все строки из левой таблицы и совпадающие строки из правой таблицы. Если совпадений нет, результатом будет null для правой таблицы.

using (var context = new SchoolContext())
{
var query = from student in context.Students
join enrollment in context.Enrollments
on student.StudentId equals enrollment.StudentId
into studentEnrollments
from se in studentEnrollments.DefaultIfEmpty()
select new
{
StudentName = student.Name,
Course = se?.Course ?? "No Course"
};

foreach (var item in query.ToList())
{
Console.WriteLine($"Student: {item.StudentName}, Course: {item.Course}");
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔6👍41
🤔 В чем разница между процессами и потоками?

Процессы — это независимые экземпляры программ, имеющие собственное адресное пространство. Потоки — это более лёгкие единицы выполнения, которые делят память и ресурсы внутри одного процесса. Потоки более экономичны в плане ресурсов, но сложнее в управлении из-за общих данных. Процессы изолированы друг от друга, что делает их более безопасными, но затратными.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1🔥1
🤔 Если в двух переменных хранится одинаковое значение, то будут ли они равны?

Сравнение значений переменных может зависеть от типа данных, хранящихся в этих переменных, и от способа их сравнения.

🟠Примитивные типы (Value Types)
Для примитивных типов (например, int, float, char, bool) значение хранятся непосредственно в переменных, и их сравнение выполняется по значению.
int a = 5;
int b = 5;

bool areEqual = (a == b); // True


🟠Ссылочные типы (Reference Types)
Для ссылочных типов (например, классы, строки) переменные содержат ссылки на объекты в куче. Сравнение ссылочных типов по умолчанию выполняется по ссылке, а не по значению.
class Person
{
public string Name { get; set; }
}

Person person1 = new Person { Name = "Alice" };
Person person2 = new Person { Name = "Alice" };

bool areEqual = (person1 == person2); // False, потому что сравниваются ссылки


🟠Строки (Strings)
Строки являются ссылочными типами, но переопределяют операторы сравнения == и Equals для сравнения по значению.
string str1 = "Hello";
string str2 = "Hello";

bool areEqual = (str1 == str2); // True, строки сравниваются по значению


🟠Кастомные классы
Для кастомных классов можно переопределить методы Equals и GetHashCode, чтобы сравнивать объекты по значению.
class Person
{
public string Name { get; set; }

public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
return false;

Person other = (Person)obj;
return Name == other.Name;
}

public override int GetHashCode()
{
return Name.GetHashCode();
}
}

Person person1 = new Person { Name = "Alice" };
Person person2 = new Person { Name = "Alice" };

bool areEqual = person1.Equals(person2); // True


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍72
🤔 Какие проблемы могут быть при многопоточности и как их избежать?

Проблемы: состояния гонки, deadlock, livelock, взаимные блокировки и неправильная синхронизация данных. Их избегают с помощью использования примитивов синхронизации (например, lock, Monitor, Mutex), разделения ответственности между потоками, атомарных операций и минимизации общего доступа к ресурсам.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
🤔 Что надо сделать, чтобы сравнить коллекции по содержимому?

Чтобы сравнить коллекции по содержимому в C#, необходимо убедиться, что сравнение выполняется на основе значений элементов, а не ссылок на объекты. Существуют различные способы сделать это, в зависимости от типа коллекций и их содержимого.

🚩Способы сравнения

Использование `SequenceEqual`
Этот метод сравнивает две последовательности (например, списки или массивы) на основе значений элементов. Поддерживает опциональный параметр IEqualityComparer<T> для пользовательского сравнения.

🚩Пример использования `SequenceEqual` для списков

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
public static void Main()
{
var list1 = new List<int> { 1, 2, 3 };
var list2 = new List<int> { 1, 2, 3 };
var list3 = new List<int> { 3, 2, 1 };

bool areEqual = list1.SequenceEqual(list2); // True
bool areEqualDifferentOrder = list1.SequenceEqual(list3); // False

Console.WriteLine(areEqual);
Console.WriteLine(areEqualDifferentOrder);
}
}


🟠Сравнение коллекций с пользовательским компаратором
Для сравнения коллекций сложных объектов можно использовать IEqualityComparer<T>.
using System;
using System.Collections.Generic;
using System.Linq;

public class Person
{
public string Name { get; set; }
public int Age { get; set; }

public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
return false;

Person other = (Person)obj;
return Name == other.Name && Age == other.Age;
}

public override int GetHashCode()
{
return HashCode.Combine(Name, Age);
}
}

public class PersonEqualityComparer : IEqualityComparer<Person>
{
public bool Equals(Person x, Person y)
{
if (x == null || y == null)
return false;

return x.Name == y.Name && x.Age == y.Age;
}

public int GetHashCode(Person obj)
{
return obj.GetHashCode();
}
}

public class Program
{
public static void Main()
{
var list1 = new List<Person>
{
new Person { Name = "Alice", Age = 30 },
new Person { Name = "Bob", Age = 25 }
};

var list2 = new List<Person>
{
new Person { Name = "Alice", Age = 30 },
new Person { Name = "Bob", Age = 25 }
};

bool areEqual = list1.SequenceEqual(list2, new PersonEqualityComparer()); // True

Console.WriteLine(areEqual);
}
}


🟠Сравнение наборов (Sets)
Для сравнения unordered коллекций, таких как HashSet, можно использовать методы SetEquals.
using System;
using System.Collections.Generic;

public class Program
{
public static void Main()
{
var set1 = new HashSet<int> { 1, 2, 3 };
var set2 = new HashSet<int> { 3, 2, 1 };

bool areEqual = set1.SetEquals(set2); // True

Console.WriteLine(areEqual);
}
}


🟠Сравнение словарей (Dictionaries)
Для сравнения словарей можно сравнивать их ключи и значения.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍41
🤔 Что такое IEnumerable?

IEnumerable — это интерфейс в .NET для перебора коллекций с помощью цикла foreach. Он предоставляет метод GetEnumerator, возвращающий объект, позволяющий обходить элементы коллекции по одному. Это основа для работы с последовательностями в LINQ и других структурах данных.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥3
🤔 Что нужно сделать, чтобы передать класс в качестве ключа?

Для того чтобы использовать экземпляры класса в качестве ключей в коллекциях, таких как Dictionary<TKey, TValue>, HashSet<T>, или других коллекциях, требующих уникальных ключей, необходимо обеспечить правильное поведение методов GetHashCode и Equals. Эти методы используются для определения уникальности и сравнения объектов.

🚩Шаги

1⃣Переопределите метод `GetHashCode`
Этот метод должен возвращать хеш-код для объекта. Хеш-код должен быть одинаковым для объектов, которые считаются равными.
2⃣Переопределите метод `Equals`
Этот метод должен определять, равны ли два объекта. Он должен сравнивать значения всех полей, которые определяют уникальность объекта.
3⃣Рассмотрите использование `IEquatable<T>`
Реализация IEquatable<T> может улучшить производительность и предоставить более явный контракт для сравнения объектов.

🚩Пример класса с переопределением `GetHashCode` и `Equals`

public class Person : IEquatable<Person>
{
public string Name { get; set; }
public int Age { get; set; }

// Переопределение Equals
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
return false;

Person other = (Person)obj;
return Name == other.Name && Age == other.Age;
}

// Реализация IEquatable<Person>.Equals
public bool Equals(Person other)
{
if (other == null)
return false;

return Name == other.Name && Age == other.Age;
}

// Переопределение GetHashCode
public override int GetHashCode()
{
return HashCode.Combine(Name, Age);
}
}


Использование класса в качестве ключа в словаре
public class Program
{
public static void Main()
{
var personDictionary = new Dictionary<Person, string>();

var person1 = new Person { Name = "Alice", Age = 30 };
var person2 = new Person { Name = "Bob", Age = 25 };

personDictionary[person1] = "Engineer";
personDictionary[person2] = "Doctor";

// Поиск по ключу
if (personDictionary.TryGetValue(new Person { Name = "Alice", Age = 30 }, out string profession))
{
Console.WriteLine($"Alice's profession is {profession}");
}
}
}


🚩Основные моменты

🟠Переопределение `Equals`
Метод Equals должен возвращать true для объектов, которые считаются равными. Сравнивайте все значимые поля объекта.
🟠Переопределение `GetHashCode`
Метод GetHashCode должен возвращать одинаковые хеш-коды для объектов, которые считаются равными. Используйте комбинацию значимых полей для вычисления хеш-кода. В .NET Core и .NET 5+ рекомендуется использовать HashCode.Combine.
🟠Реализация `IEquatable<T>`
Реализация интерфейса IEquatable<T> улучшает производительность и ясность кода. Метод Equals(T other) должен содержать ту же логику, что и Equals(object obj).

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
🤔 В чем отличие Dispose и Finalize?

Dispose освобождает неуправляемые ресурсы явно, обычно через реализацию интерфейса IDisposable. Finalize вызывается сборщиком мусора автоматически для очистки перед удалением объекта, но менее предсказуем. Для надёжного освобождения ресурсов рекомендуется использовать Dispose.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🤔 Как по ключу получить значение?

Для получения значения по ключу в словаре (Dictionary<TKey, TValue>) используются методы и свойства, такие как индексатор [], метод TryGetValue, и метод ContainsKey.

🟠Индексатор `[]`
Индексатор позволяет получить значение по ключу напрямую. Если ключ отсутствует в словаре, будет выброшено исключение KeyNotFoundException.
var dictionary = new Dictionary<int, string>
{
{ 1, "One" },
{ 2, "Two" },
{ 3, "Three" }
};

try
{
string value = dictionary[2]; // Получение значения по ключу 2
Console.WriteLine(value); // Выведет "Two"
}
catch (KeyNotFoundException)
{
Console.WriteLine("Key not found");
}


🟠Метод `TryGetValue`
Метод TryGetValue позволяет безопасно получить значение по ключу. Он возвращает true, если ключ найден, и false, если ключ отсутствует. При этом значение записывается в выходной параметр.
var dictionary = new Dictionary<int, string>
{
{ 1, "One" },
{ 2, "Two" },
{ 3, "Three" }
};

if (dictionary.TryGetValue(2, out string value))
{
Console.WriteLine(value); // Выведет "Two"
}
else
{
Console.WriteLine("Key not found");
}


🟠Метод `ContainsKey`
Метод ContainsKey проверяет наличие ключа в словаре. Его можно использовать в сочетании с индексатором для получения значения.
var dictionary = new Dictionary<int, string>
{
{ 1, "One" },
{ 2, "Two" },
{ 3, "Three" }
};

if (dictionary.ContainsKey(2))
{
string value = dictionary[2];
Console.WriteLine(value); // Выведет "Two"
}
else
{
Console.WriteLine("Key not found");
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
🤔 Может ли быть несколько блоков catch?

Да, в C# можно использовать несколько блоков catch для обработки разных типов исключений. Это позволяет задавать индивидуальную логику для каждого типа ошибки, начиная с более специфичных и заканчивая более общими исключениями.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
🤔 Что должен возвращать Get hashcode?

Должен возвращать целое число (int), которое представляет хеш-код объекта. Этот хеш-код используется структурами данных, такими как хеш-таблицы (например, Dictionary<TKey, TValue>, HashSet<T>), для быстрого поиска, вставки и удаления объектов.

🚩Основные требования к реализации `GetHashCode`

🟠Согласованность с `Equals`
Если два объекта равны (по методу Equals), то их хеш-коды должны быть одинаковыми. Если Equals возвращает true для двух объектов, их GetHashCode должны возвращать одинаковые значения.

🟠Постоянство
Метод GetHashCode должен возвращать одно и то же значение для одного и того же объекта в пределах одного запуска приложения, при условии, что состояние объекта не изменяется.

🟠Рассеивание
Хороший хеш-функция должна равномерно распределять значения хеш-кодов, чтобы минимизировать количество коллизий (когда разные объекты имеют одинаковые хеш-коды).

🚩Примеры реализации `GetHashCode`

Простой пример для одного поля
public class Person
{
public string Name { get; set; }

public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
return false;

Person other = (Person)obj;
return Name == other.Name;
}

public override int GetHashCode()
{
return Name == null ? 0 : Name.GetHashCode();
}
}


Пример для нескольких полей
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }

public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
return false;

Person other = (Person)obj;
return FirstName == other.FirstName && LastName == other.LastName && Age == other.Age;
}

public override int GetHashCode()
{
unchecked // Помогает избежать исключений при переполнении
{
int hash = 17;
hash = hash * 23 + (FirstName == null ? 0 : FirstName.GetHashCode());
hash = hash * 23 + (LastName == null ? 0 : LastName.GetHashCode());
hash = hash * 23 + Age.GetHashCode();
return hash;
}
}
}


Использование HashCode.Combine (начиная с .NET Core 2.1)
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }

public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
return false;

Person other = (Person)obj;
return FirstName == other.FirstName && LastName == other.LastName && Age == other.Age;
}

public override int GetHashCode()
{
return HashCode.Combine(FirstName, LastName, Age);
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍42
🤔 Для чего нужны нереляционные базы данных?

Нереляционные базы данных (NoSQL) используются для работы с большими объёмами данных, структурированных или неструктурированных, а также для обеспечения гибкости и масштабируемости. Они подходят для хранения документов, ключей-значений, графов или временных рядов. Такие базы, как MongoDB или Redis, идеальны для приложений с динамической структурой данных или высокой нагрузкой.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
🤔 Как в кучах разделяются объекты?

В .NET среде управления памятью, объекты размещаются в куче (heap), и управление памятью осуществляется сборщиком мусора (Garbage Collector, GC). Куча разделена на несколько поколений для оптимизации производительности управления памятью.

🚩Поколения кучи

Куча в .NET разделена на три поколения: Generation 0, Generation 1 и Generation 2. Это разделение позволяет эффективно управлять памятью, минимизируя частоту сборок мусора и оптимизируя их выполнение.

🟠Generation 0
Содержит новосозданные объекты. Сборка мусора для этого поколения происходит чаще, так как большинство объектов "умирает" быстро. Наименьший размер среди всех поколений.

🟠Generation 1
Промежуточное поколение, используемое для объектов, которые пережили хотя бы одну сборку мусора Generation 0. Содержит объекты с более длительным временем жизни, чем объекты в Generation 0.

🟠Generation 2
Содержит объекты с самым длительным временем жизни. Наибольший размер среди всех поколений. Сборка мусора для этого поколения происходит реже всего.

🚩Large Object Heap (LOH)

LOH используется для размещения крупных объектов (размером 85,000 байт и более). Объекты в LOH не перемещаются при сборке мусора, что уменьшает фрагментацию памяти. Сборка мусора для LOH происходит одновременно со сборкой Generation 2.

🚩Как разделяются объекты

🟠Размещение объектов
При создании объекта он сначала размещается в Generation 0. Если объект переживает сборку мусора в Generation 0, он перемещается в Generation 1. Если объект переживает сборку мусора в Generation 1, он перемещается в Generation 2.

🟠Сборка мусора
Generation 0: Быстрая и частая сборка. Цель - освободить память от краткоживущих объектов.
Generation 1: Реже, чем Generation 0. Служит промежуточной зоной.
Generation 2: Самая редкая и длительная сборка. Обрабатывает долгоживущие объекты.
Large Object Heap (LOH): Сборка мусора проводится вместе с Generation 2.

public class Program
{
public static void Main()
{
// Создание объектов в Generation 0
for (int i = 0; i < 1000; i++)
{
var obj = new object();
}

// Создание большого объекта (размещается в LOH)
byte[] largeArray = new byte[100000];

// Принудительный вызов сборщика мусора
GC.Collect();

// Проверка поколения объекта
Console.WriteLine(GC.GetGeneration(largeArray)); // Скорее всего, 2
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10👾1
🤔 В чем разница между асинхронностью и многопоточностью?

Асинхронность и многопоточность — это два подхода к параллельной обработке задач. Асинхронность позволяет программе продолжать выполнение работы, в то время как она ждет завершения другой задачи (например, ввода/вывода), не блокируя основной поток. Многопоточность включает использование нескольких потоков для выполнения различных задач одновременно, что может ускорить выполнение программы за счет одновременной обработки данных.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5👍1
🤔 Какие кучи существуют?

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

🚩Управляемая куча (Managed Heap)

Это основная область памяти, используемая средой выполнения .NET для управления динамически выделенной памятью. Она разделена на поколения для оптимизации производительности сборки мусора.
🟠Generation 0 (Gen 0)
Содержит новосозданные объекты. Сборка мусора в этом поколении происходит чаще всего. Маленький размер, рассчитанный на быстрое освобождение памяти от краткоживущих объектов.

🟠Generation 1 (Gen 1)
Промежуточное поколение. Объекты, которые пережили сборку мусора в Generation 0, перемещаются в Generation 1. Средний размер, служит буфером между краткоживущими и долгоживущими объектами.

🟠Generation 2 (Gen 2)
Содержит объекты с длительным временем жизни. Объекты, которые пережили сборку мусора в Generation 1, перемещаются в Generation 2. Сборка мусора в этом поколении происходит реже всего. Самый большой размер среди всех поколений.

public class Program
{
public static void Main()
{
// Создание объектов в Generation 0
for (int i = 0; i < 1000; i++)
{
var obj = new object();
}

// Принудительный вызов сборщика мусора
GC.Collect();

// Проверка поколения объекта
var objGen2 = new object();
GC.Collect();
Console.WriteLine(GC.GetGeneration(objGen2)); // Скорее всего, 2
}
}


🚩Куча больших объектов (Large Object Heap, LOH)

Куча больших объектов используется для размещения крупных объектов (размером 85,000 байт и более). LOH имеет свои особенности:

🟠Отсутствие перемещения
Объекты в LOH не перемещаются при сборке мусора, что уменьшает фрагментацию памяти.
🟠Сборка мусора
Сборка мусора для LOH происходит вместе с Generation 2.

public class Program
{
public static void Main()
{
// Создание большого объекта (размещается в LOH)
byte[] largeArray = new byte[100000];

// Принудительный вызов сборщика мусора
GC.Collect();

// Проверка поколения объекта
Console.WriteLine(GC.GetGeneration(largeArray)); // Скорее всего, 2
}
}


🚩Сегментированные кучи (Segmented Heaps)

Сегментированные кучи используются в серверной сборке мусора (Server GC), где для каждой логической обработки (ядра процессора) создается отдельная куча:

🟠Многопоточность
Позволяет более эффективно использовать многопроцессорные системы.
🟠Изоляция
Каждое ядро работает со своим сегментом памяти, что уменьшает конкуренцию за доступ к памяти.

🚩Упрощенная куча (Ephemeral Heap)

Упрощенная куча представляет собой комбинацию Generation 0 и Generation 1 и используется для оптимизации управления краткоживущими объектами. Этот термин чаще встречается в контексте описания поведения сборщика мусора.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
🤔 В чем разница между процессами и потоками?

Процессы — это независимые экземпляры программ, имеющие собственное адресное пространство. Потоки — это более лёгкие единицы выполнения, которые делят память и ресурсы внутри одного процесса. Потоки более экономичны в плане ресурсов, но сложнее в управлении из-за общих данных. Процессы изолированы друг от друга, что делает их более безопасными, но затратными.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5👍1
🤔 Для чего нужно разделение Large object heap и small object heap?

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

🚩Основные причины

🟠Оптимизация производительности сборщика мусора (GC)
Малые объекты (SOH): Малые объекты имеют более короткий жизненный цикл и размещаются в поколениях (Gen 0, Gen 1 и Gen 2). Сборка мусора для этих объектов происходит чаще и быстрее.
Большие объекты (LOH): Большие объекты имеют тенденцию жить дольше, и сборка мусора для них происходит реже, вместе с Generation 2. LOH не перемещает объекты в памяти, что уменьшает фрагментацию.

🟠Уменьшение фрагментации памяти
SOH: Частые сборки мусора и перемещение объектов в памяти могут вызвать фрагментацию. Однако малые объекты легче перемещать и собирать.
LOH: Большие объекты не перемещаются сборщиком мусора, что уменьшает фрагментацию, но может привести к тому, что большие блоки памяти не будут эффективно использоваться.

🟠Различные стратегии аллокации
SOH: Использует компактные аллокаторы, что обеспечивает эффективное использование памяти для малых объектов и минимизирует накладные расходы.
LOH: Большие объекты требуют более значительных блоков памяти, и их аллокация и деаллокация управляются отдельно для оптимизации использования этих больших блоков.

🚩Плюсы

Эффективное управление памятью
Разделение позволяет лучше управлять памятью для малых и больших объектов, минимизируя накладные расходы и улучшая производительность.
Уменьшение фрагментации
Фрагментация памяти уменьшается, так как большие объекты не перемещаются в памяти, а малые объекты легче компактируются.
Повышение производительности GC
Сборка мусора для малых объектов происходит быстро и часто, тогда как сборка для больших объектов — реже и более эффективно.

🚩Пример использования

Размещение малых объектов (SOH)
public class Program
{
public static void Main()
{
// Создание малых объектов в SOH
for (int i = 0; i < 1000; i++)
{
var obj = new object();
}

// Принудительная сборка мусора для малых объектов
GC.Collect(0); // Сборка мусора для Generation 0
}
}


Размещение больших объектов (LOH)
public class Program
{
public static void Main()
{
// Создание большого объекта в LOH
byte[] largeArray = new byte[100000]; // Размер больше 85,000 байт

// Принудительная сборка мусора
GC.Collect(2); // Сборка мусора для Generation 2 и LOH
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
🤔 В чем разница между процессами и потоками?

Процессы — это независимые экземпляры программ, имеющие собственное адресное пространство. Потоки — это более лёгкие единицы выполнения, которые делят память и ресурсы внутри одного процесса. Потоки более экономичны в плане ресурсов, но сложнее в управлении из-за общих данных. Процессы изолированы друг от друга, что делает их более безопасными, но затратными.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
🤔 Чем от Lock`а отличаются mutex и семафор?

Lock (монитор), Mutex и Semaphore – это три механизма синхронизации, используемые для управления доступом к общим ресурсам в многопоточном программировании. Хотя все они служат для синхронизации потоков, их поведение и случаи использования различаются.

🟠`Lock` (Монитор)
Lock (в C# используется ключевое слово lock) или Monitor – это механизм синхронизации, который позволяет одному потоку захватить блокировку для определенной области кода, чтобы другие потоки не могли войти в эту область кода до освобождения блокировки.
Область действия: Только внутри одного процесса.
Рекурсивность: Поддерживает рекурсивные блокировки (один и тот же поток может захватить блокировку несколько раз).
Простота использования: Легко использовать с ключевым словом lock.
private readonly object _lockObject = new object();

public void CriticalSection()
{
lock (_lockObject)
{
// Критическая секция
}
}


🟠`Mutex`
Mutex (Mutual Exclusion) – это более сложный механизм синхронизации, который может использоваться для синхронизации потоков как внутри одного процесса, так и между разными процессами.
Область действия: Может использоваться как внутри одного процесса, так и между разными процессами.
Рекурсивность: Не поддерживает рекурсивные блокировки по умолчанию.
Использование: Требует явного захвата и освобождения блокировки.
private readonly Mutex _mutex = new Mutex();

public void CriticalSection()
{
_mutex.WaitOne(); // Захват мьютекса
try
{
// Критическая секция
}
finally
{
_mutex.ReleaseMutex(); // Освобождение мьютекса
}
}


🟠`Semaphore`
Semaphore – это механизм синхронизации, который ограничивает доступ к ресурсу заданным количеством потоков одновременно. Существует два типа семафоров: Semaphore и SemaphoreSlim.
Область действия: Может использоваться для синхронизации потоков внутри одного процесса (SemaphoreSlim) и между разными процессами (Semaphore).
Многократный доступ: Позволяет нескольким потокам одновременно получать доступ к ресурсу, если количество разрешений больше нуля.
Использование: Требует явного захвата и освобождения разрешения.
private readonly Semaphore _semaphore = new Semaphore(3, 3); // Максимум 3 потока

public void CriticalSection()
{
_semaphore.WaitOne(); // Захват семафора
try
{
// Критическая секция
}
finally
{
_semaphore.Release(); // Освобождение семафора
}
}


🚩Ключевые различия

🟠Область действия
Lock: Только внутри одного процесса.
Mutex: Может использоваться для синхронизации между процессами.
Semaphore: Может использоваться для синхронизации между процессами (Semaphore) и внутри одного процесса (SemaphoreSlim).

🟠Рекурсивность
Lock: Поддерживает рекурсивные блокировки.
Mutex: Не поддерживает рекурсивные блокировки по умолчанию.
Semaphore: Не поддерживает рекурсивные блокировки.

🟠Многократный доступ
Lock: Только один поток может захватить блокировку.
Mutex: Только один поток может захватить блокировку.
Semaphore: Несколько потоков могут захватить блокировку одновременно, если разрешений больше нуля.

🟠Простота использования
Lock: Легко использовать с ключевым словом lock.
Mutex: Требует явного захвата и освобождения блокировки.
Semaphore: Требует явного захвата и освобождения разрешений.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍63