C# 1001 notes
6.61K subscribers
412 photos
14 videos
2 files
356 links
Регулярные короткие заметки по C# и .NET.

Просто о сложном для каждого.

admin - @haarrp
Download Telegram
🚀 C# 15 меняет подход к `unsafe`: указатели больше не означают автоматически опасный код

Раньше в C# сам факт использования указателя требовал:


unsafe
{
int* ptr;
}


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

опасным считается не наличие указателя, а операция, которая реально работает с unmanaged-памятью.

В preview-версии C# 15 уже не требуют unsafe:

объявление pointer-типа
получение адреса через &
fixed для закрепления памяти
преобразование stackalloc в указатель
sizeof для unmanaged-типов

Пример:


int number = 42;

int* pointer = &number;

int[] numbers = [10, 20, 30];

fixed (int* first = numbers)
{
// само закрепление памяти безопасно
}


Но вот это всё ещё требует unsafe:


*pointer; // dereference
pointer->Value; // доступ через указатель
pointer[0]; // работа с элементами
delegate*<> // вызов function pointer


Главная идея:

**создать инструмент можно безопасно.
Опасно — когда начинаешь напрямую менять память.**

Это первый этап большой переработки модели безопасности C#.

Дальше ожидаются:

- requires-unsafe для отдельных членов;
- opt-in на уровне assembly;
- новый safe keyword.

C# постепенно делает unsafe-код более точечным: меньше блоков вокруг всего файла, больше внимания к реально опасным операциям.

#csharp #dotnet #programming
⚡️ C#-приём: не привязывай метаданные к объектам через обычный `Dictionary` — иногда нужен `ConditionalWeakTable`.

Допустим, библиотека кеширует данные о типах:


private static readonly Dictionary<Type, Metadata> Cache = new();


В обычном приложении это может годами работать без проблем.

Но если используются plugins, dynamic assemblies или unloadable AssemblyLoadContext, такой словарь способен удерживать Type, а вместе с ним — всю загруженную сборку.

И получить memory leak.

Для таких случаев в .NET есть малоизвестный:


ConditionalWeakTable<TKey, TValue>


Пример:


private static readonly ConditionalWeakTable<Type, Metadata> Cache = new();

static Metadata GetMetadata(Type type)
{
return Cache.GetValue(type, BuildMetadata);
}


Ключ здесь хранится слабо.

Если Type больше нигде не нужен, GC может его собрать, а связанная запись автоматически исчезнет из таблицы.

Это особенно полезно для:

* reflection-кешей;
* proxy/framework-кода;
* source/runtime metadata;
* plugin-систем;
* приложений с AssemblyLoadContext.

🔥 Если видишь:


static Dictionary<Type, ...>


или


static ConcurrentDictionary<Type, ...>


в коде, который работает с динамически загружаемыми сборками, стоит проверить:

не удерживает ли этот кеш сборки в памяти навсегда?

Иногда правильный ответ — ConditionalWeakTable.

#CSharp #DotNet #Backend #Programming #CLR