Если вы получаете IDisposable зависимость в конструкторе:
Пример
class ClassA : IDisposable { ... }
class ClassB : IDisposable
{
private readonly ClassA _a;
private readonly HeavyResource _resource;
public ClassB(ClassA a)
{
_a = a;
_resource = new();
}
public Dispose()
{
_resource.Dispose(); // хорошо
_a.Dispose(); // хорошо. Или плохо?
}
}
class ClassC(ClassA a)
{
public void DoTheThing()
{
using (var b = new ClassB(a))
{
// ...
}
// если ClassA был зарегистрирован в DI как AddScoped<ClassA>(),
// экземпляр больше не юзабелен
a.DoTheThing(); // ObjectDisposedException
}
}
бывают случаи, когда диспоузить её будет ошибкой. Например, у ClassA время жизни - скоуп, а ClassB предполалось использовать как короткоживущий объект.
Вы можете подумать: "Да ну, это ерунда какая-то" - ну, возможно будете правы. Идея в том, что, например, в отличие от Rust, в C# непонятно, когда объекты временно заимствуются (и чистить не надо), а когда передаются во владение со всеми соответствующими заботами (и чистить надо). Каждый выкручивается как может, вот у Microsoft самих полно примеров:
public HttpClient(HttpMessageHandler handler, bool disposeHandler);
или
public StreamReader(Stream stream, ..., bool leaveOpen = false);
Это тоже не так :) Сборщик мусора ничего про интерфейс не знает: если пользователь IDisposable явно не вызовет Dispose (using считается) ничего не произойдёт.
IDisposable - это такой механизм кооперативного детерминированного освобождения ресурсов.
И да, как подсказывают выше, необязательно неуправляемых. Тут Microsoft несколько вводит в заблуждение в своей собственной документации.
Свойства и в особенности автоматические свойства тоже резко изменяются во время компиляции.
<...>
Мало того, сам _backingField - это что-то от Roslyn. (я полагаю так).
Поле называется <Count>k__BackingField - да, вместе со скобками. Это невалидное имя в C# - чтобы случайно не получить конфликт с пользовательским кодом - но вполне себе нормальное в CLR.
Когда вы используете IDisposable-производные,они не находятся в неуправляемой куче. Тем не менее, вы вынуждены явно указывать область жизни таких классов.
Не совсем. Во-первых, .NET не мешает забыть вызвать Dispose, но в большинстве случаев это будет ошибкой, иногда незначительной (ресурс освободится, просто в какое-то непонятное время потом), иногда критической (будет течь память).
Во-вторых, есть ситуации, когда вызыватьDisposeне надо. Например, если класс получает IDisposable (типа scoped DbContext) извне как зависимость.
Странный спор у вас тут происходит, но ваша собственная ссылка различает elvis (a ?: b) и тернарный (a ? b : c) операторы. У них же даже арность разная, как они могут быть одним и тем же.
А если говорить про C#, у нас под elvis'ом всегда понимался null-conditional operator (?.), а тернарный всегда был тернарным.
Не знаю. Не хочу умалять ваш труд, но я тоже не вижу для себя применение этой штуки. Чем старше я становлюсь, тем больше ценю подходы потупее и попроще.
Надо подружить два класса - можно повесить internal и положить в отдельную сборку (хотелось бы в дотнете модулей поменьше, как в Rust, ну да ладно). Либо через explicit interface implementation, чтобы методы или свойства не отсвечивали в intellisense. Либо скрыть через EditorBrowsable(Never). Либо как в EF Core - положить в Internal namespace и написать анализатор. Влезть можно - но на свой страх и риск. В конце концов, знак "Осторожно! Злая собака" не призван запретить вам перелезать через забор, только лишний раз подумать ;)
Большой плюс подходов выше - они простые, используются много лет и всем знакомы. Если разработчик увидит EditorBrowsable(Never) - он поймёт что это такое и для чего.
Большой минус OnlyYou<T> - сложность её понимания превосходит пользу, которую она приносит. Имхо, конечно.
ПС. Поставил вам плюсик за готовность воспринимать критику. Эта статья читается намного проще.
Несколько лет назад я бы сам ворчал, дескать, JSON - текстовый формат, расточительно, неэффективно, бу-бу-бу. Сейчас у нас есть парсеры, ворочающие JSONы гигабайтами в секунду.
Вы никак не отнимите у JSON его огромный плюс - он поддерживается практически любым языком программирования, можно читать даже на тостере или утюге. Так уж сложилось. Поздно брюзжать про бинарные СТАНДАРТНЫЕ форматы.
Вот бы человечество придумало что-то вроде анализатора, который бы находил неиспользуемый код в библиотеках (и в пользовательском коде тоже можно, кстати) и удалял из скомпилированного артефакта. Можно даже придумать какое-нибудь прикольное название, например, tree shaking. Тогда не станет проблемы +10 Мб, а библиотеки останутся полезными.
У меня ощущение, что где-то заканчивается онлайн-курс по ИИ и всем выдали финальную домашку навайбкодить продукт и написать статью на хабр о том, как добиться успешного успеха, обязательно с выводами и горсткой советов.
А вот когда люди поймут, что те, кто продвигал Open Source, тупо отдали благосостояние всей индустрии капиталистам
Можно подумать, отсутствие открытого кода остановило бы ИИ-компании. Авторы 500 тысяч книжек кому что отдали? "Капиталистам" это просто стоило 1,5 миллиарда президентов США - дороговато, но никто даже за решётку не сел.
Хммм. Я полез разбираться, оказывается, чтобы на винде в Edge тоже заработало, странице нужно явно проставлять метаданные через Media Session API. После этого работает пауза, хотя трек надо включать вручную:
navigator.mediaSession.metadata = new MediaMetadata({
title: 'DevOpsRadio',
artist: 'boombick',
});
Трек начинает ставиться на паузу/воспроизводиться по ⏯️, но страница не понимает, что что-то произошло:
но при остановке трека кнопки снова перестают работать. Gemini говорит, вот это
this.mainAudio = null;
прибивает медиа сессию и советует вместо зануления mainAudio прибивать src:
// Inside stop()...
this.mainAudio.removeAttribute('src'); // Better than src = ''
this.mainAudio.load(); // Forces the browser to drop the network connection
// Inside play()...
this.mainAudio.src = '/radio/stream'; // Re-assign the stream
А у меня тоже вопрос в догонку к предложениям выше :)
Можно ли привязать медиа-клавиши к странице? То есть чтобы по клавишам Play/Pause на клавиатуре можно было включать/ставить на паузу, например, как это происходит с вкладками YouTube.
Если вы получаете
IDisposableзависимость в конструкторе:Пример
бывают случаи, когда диспоузить её будет ошибкой. Например, у
ClassAвремя жизни - скоуп, аClassBпредполалось использовать как короткоживущий объект.Вы можете подумать: "Да ну, это ерунда какая-то" - ну, возможно будете правы. Идея в том, что, например, в отличие от Rust, в C# непонятно, когда объекты временно заимствуются (и чистить не надо), а когда передаются во владение со всеми соответствующими заботами (и чистить надо). Каждый выкручивается как может, вот у Microsoft самих полно примеров:
или
Это тоже не так :) Сборщик мусора ничего про интерфейс не знает: если пользователь
IDisposableявно не вызоветDispose(usingсчитается) ничего не произойдёт.IDisposable- это такой механизм кооперативного детерминированного освобождения ресурсов.И да, как подсказывают выше, необязательно неуправляемых. Тут Microsoft несколько вводит в заблуждение в своей собственной документации.
Небольшие замечания:
Поле называется
<Count>k__BackingField- да, вместе со скобками. Это невалидное имя в C# - чтобы случайно не получить конфликт с пользовательским кодом - но вполне себе нормальное в CLR.Не совсем. Во-первых, .NET не мешает забыть вызвать
Dispose, но в большинстве случаев это будет ошибкой, иногда незначительной (ресурс освободится, просто в какое-то непонятное время потом), иногда критической (будет течь память).Во-вторых, есть ситуации, когда вызывать
Disposeне надо. Например, если класс получаетIDisposable(типа scopedDbContext) извне как зависимость.Странный спор у вас тут происходит, но ваша собственная ссылка различает elvis (
a ?: b) и тернарный (a ? b : c) операторы. У них же даже арность разная, как они могут быть одним и тем же.А если говорить про C#, у нас под elvis'ом всегда понимался null-conditional operator (
?.), а тернарный всегда был тернарным.Не знаю. Не хочу умалять ваш труд, но я тоже не вижу для себя применение этой штуки. Чем старше я становлюсь, тем больше ценю подходы потупее и попроще.
Надо подружить два класса - можно повесить
internalи положить в отдельную сборку (хотелось бы в дотнете модулей поменьше, как в Rust, ну да ладно). Либо через explicit interface implementation, чтобы методы или свойства не отсвечивали в intellisense. Либо скрыть черезEditorBrowsable(Never). Либо как в EF Core - положить вInternalnamespace и написать анализатор. Влезть можно - но на свой страх и риск. В конце концов, знак "Осторожно! Злая собака" не призван запретить вам перелезать через забор, только лишний раз подумать ;)Большой плюс подходов выше - они простые, используются много лет и всем знакомы. Если разработчик увидит
EditorBrowsable(Never)- он поймёт что это такое и для чего.Большой минус
OnlyYou<T>- сложность её понимания превосходит пользу, которую она приносит. Имхо, конечно.ПС. Поставил вам плюсик за готовность воспринимать критику. Эта статья читается намного проще.
Почему?
А. Ну я на стадии принятия :)
А что не так с pwsh?
Да тут у многих беда с хабами.
Упомянули интернет - фигачим хаб дотнета! А что, .NET, интернет - да какая разница, похоже же.
Или человек бухтит про что-то своё жизненное, упоминает как 10 лет назад юзал EntityFramework - всё, пихаем в хаб с сишарпом!
/me вздыхает
Вы правы :)
Очевидно, что JSON - good enough, он не идеален и подходит не во всех ситуациях.
Несколько лет назад я бы сам ворчал, дескать, JSON - текстовый формат, расточительно, неэффективно, бу-бу-бу. Сейчас у нас есть парсеры, ворочающие JSONы гигабайтами в секунду.
Вы никак не отнимите у JSON его огромный плюс - он поддерживается практически любым языком программирования, можно читать даже на тостере или утюге. Так уж сложилось. Поздно брюзжать про бинарные СТАНДАРТНЫЕ форматы.
Вот бы человечество придумало что-то вроде анализатора, который бы находил неиспользуемый код в библиотеках (и в пользовательском коде тоже можно, кстати) и удалял из скомпилированного артефакта. Можно даже придумать какое-нибудь прикольное название, например, tree shaking. Тогда не станет проблемы +10 Мб, а библиотеки останутся полезными.
Приехали вот сегодня в мои края :)
У меня ощущение, что где-то заканчивается онлайн-курс по ИИ и всем выдали финальную домашку навайбкодить продукт и написать статью на хабр о том, как добиться успешного успеха, обязательно с выводами и горсткой советов.
Можно подумать, отсутствие открытого кода остановило бы ИИ-компании. Авторы 500 тысяч книжек кому что отдали? "Капиталистам" это просто стоило 1,5 миллиарда президентов США - дороговато, но никто даже за решётку не сел.
Хммм. Я полез разбираться, оказывается, чтобы на винде в Edge тоже заработало, странице нужно явно проставлять метаданные через Media Session API. После этого работает пауза, хотя трек надо включать вручную:
Трек начинает ставиться на паузу/воспроизводиться по ⏯️, но страница не понимает, что что-то произошло:
Можно добавить обработчики...
но при остановке трека кнопки снова перестают работать. Gemini говорит, вот это
прибивает медиа сессию и советует вместо зануления
mainAudioприбиватьsrc:@boombick не посмотрите? 🙏
А у меня тоже вопрос в догонку к предложениям выше :)
Можно ли привязать медиа-клавиши к странице? То есть чтобы по клавишам Play/Pause на клавиатуре можно было включать/ставить на паузу, например, как это происходит с вкладками YouTube.
Никто не мешает. В том числе никто не мешает ИИ-агентам смотреть ваш код и безвозмездно обучаться на нём. Читайте новости в оригинале:
Забьют на онлайн-собеседования. Или будут просить включить вторую камеру, которая бы смотрела в монитор