Comments 15
При использовании временных зависимостей (
Transient
) нет четкого понимания, когда ресурсы будут освобождены
Что-то я не понял или туплю, но вроде Transient должен автоматически уничтожаться GC при окончании вызова согласно документации.
Что-то там в документации фигня написана.
Transient-то объектами никто не владеет, а потому они вообще не освобождаются.
Transient уничтожается только когда scope, в рамках которого он был создан, будет уничтожен. В документации почти все верно написано, только не конкретизировано. На каждый request создается scope, поэтому transient зависимости будут нормально уничтожаться после завершения запроса.
Но если объект будет создан в рамках глобального скоупа самого контейнера, то и уничтожен он будет только когда контейнер уничтожат.
Хм, и правда:
using Microsoft.Extensions.DependencyInjection;
var services = new ServiceCollection();
services.AddTransient<Tracker>();
var sp = services.BuildServiceProvider();
var scope = sp.CreateScope();
Console.WriteLine("Scope created");
scope.ServiceProvider.GetRequiredService<Tracker>();
scope.Dispose();
Console.WriteLine("Scope disposed");
sp.Dispose();
Console.WriteLine("Service provider disposed");
class Tracker : IDisposable
{
public Tracker()
{
Console.WriteLine("Created");
}
public void Dispose()
{
Console.WriteLine("Disposed!");
}
}
А зачем реализовывать IDisposable для управляемых ресурсов? IDisposable придуман, чтобы освобождать неуправляемые ресурсы. Вызов Dispose не означает, что объект будет уничтожен сборщиком мусора. https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-dispose
У вас объекты в памяти висят, значит их держит ссылка какая-то, профилировщик памяти в помощь.
Самое простое — чтобы вызвать Dispose у неуправляемого ресурса по цепочке. Также какой-либо внутренний объект может при освобождении возвращаться в пул.
Насчет пула, вот уж точно плохая идея, полагаться на Dispose для возврата объектов в пул. Ладно еще вы один когда над проектом работаете, а если несколько человек или либу делаете и быть уверенным, что Dispose будут вызывать непосредственно, так себе идея. Тут или не используйте пул или взял, попользовался и верни назад или смысла от пула тогда нет, если, например, вы берете объект из пула на время жизни приложения.
Ну и самое главное, вызов Dispose никак не влияет на освобождение объекта сборщиком мусора.
Тут или не используйте пул или взял, попользовался и верни назад
Вот-вот: взял, попользовался и вызвал Dispose. А есть ли там внутри пул, или неуправляемые ресурсы, или что-то ещё — вообще не должно волновать.
Ладно еще вы один когда над проектом работаете, а если несколько человек или либу делаете и быть уверенным, что Dispose будут вызывать непосредственно, так себе идея
Почему вы доверяете коллегам в плане возврата в пул (что является ручной операцией которую легко забыть), но не доверяете в плане вызова Dispose (чему помогают using и анализаторы кода)?
Ну и самое главное, вызов Dispose никак не влияет на освобождение объекта сборщиком мусора.
Спасибо, Капитан Очевидность!
>IDisposable придуман, чтобы освобождать неуправляемые ресурсы
Ошибаетесь, например отписку от события удобно делать в Dispose. Кроме того может быть зависимость от другого IDisposable, и совершенно без разницы что там делается в Dispose: если тип требует вызова Dispose он должен быть вызван.
Официальная документация гласит именно так. Насчет зависимости от другого IDisposable, Dispose вызывается (если правильно этот паттерн реализован) из финализатора, перед сборкой объекта. Если в объект передается какая-то зависимость из вне, то уж ее точно не объект очищать должен, если внутри какая то зависимость, есть using.
Dispose вызывается (если правильно этот паттерн реализован) из финализатора, перед сборкой объекта
Вызывается, да нет тот. Метод Dispose()
финализатор, согласно всем известным мне паттернам, не вызывает ни прямо ни косвенно.
Кстати, упомянутый вами паттерн давно уже устарел, вместо него правильнее не допускать смешивания управляемых и неуправляемых ресурсов в одном объекте.
Если в объект передается какая-то зависимость из вне, то уж ее точно не объект очищать должен, если внутри какая то зависимость, есть using.
Это если зависимость в переменной лежит, а если в поле — ей надо вызывать Dispose вручную.
Кстати, почему вы using не считаете за вызов Dispose?
https://habr.com/ru/companies/clrium/articles/341864/ вот прочтите, сказано про все более чем
Раньше тоже писал под Xamarin / MAUI, от души сочувствую, сколько багов как в этих фреймворках больше нету негде наверное.
По истине ужасные фреймворки, проектов на них мало, вакансий ещё меньше.
Сейчас перешёл на React Native кайфую.
П.с. просто хвастаюсь)
Реализация IDisposable в моделях представлений в проектах MAUI