Мне тоже не нравится то что void не тип, а хрен пойми что. Но в целом я бы такое видео не стал записывать в 2023-м году. Потому что часть предъяв родом года из 2019-го. Тип коструктора сейчас выводится. 4 место с вложенными классами — ничего что оно именно так и задумывалось, всякие внутренние енумераторы писать?
S>Для меня самая боль была — это №3 — проверить реализует ли object obj интерфейс IContract<T>
Ну там сам автор видео приводит решение проблемы в одну строку. Для задачи с которой сталкиваются писатели фреймворков а потребители почти никогда, такая себе трудность.
S>Что у вас на первом месте?
Раз в неделю меня бесит то что Task и CancellationToken разные объекты, которые живут абсолютно независимой жизнью. Я бы таки хотел Task.Cancel() а заодно ещё и Task.Abort() по мощности примерно равный Thread.Abort.
И как пользователю мне вот вообще пофиг, насколько там сложно авторам сделать этот Abort надёжным, как там они замучаются с консистентностью, и т.д. Эта хрень с CancellationToken, которая даёт ноль гарантий что задача проверит тот токен, или не останется как зомби висеть в бесконечном цикле и жрать целый CPU — не имеет права на жизнь, чем бы там фреймворкописатели не прикрывались.
_>Раз в неделю меня бесит то что Task и CancellationToken разные объекты, которые живут абсолютно независимой жизнью. Я бы таки хотел Task.Cancel() а заодно ещё и Task.Abort() по мощности примерно равный Thread.Abort. _>И как пользователю мне вот вообще пофиг, насколько там сложно авторам сделать этот Abort надёжным, как там они замучаются с консистентностью, и т.д. Эта хрень с CancellationToken, которая даёт ноль гарантий что задача проверит тот токен, или не останется как зомби висеть в бесконечном цикле и жрать целый CPU — не имеет права на жизнь, чем бы там фреймворкописатели не прикрывались.
Меня в своё время штырило от using который не обрабатывает Thread.Abort, хотя казалось бы что мешало.
using System;
using System.Threading;
class Test {
static int counter = 0;
class A : IDisposable {
public A() {
Interlocked.Increment(ref counter);
int j = 0; for (int i = 0;i < 100000; i++) j += i;
}
public void Dispose() { Interlocked.Decrement(ref counter); }
public void fn() { }
}
static void test(string name, Action action) {
counter = 0;
for (int i = 0;i < 100;i++) {
var thread = new Thread(() => {
for(;;) action();
});
thread.Start();
thread.Abort();
}
Console.WriteLine("{0} leaks={1}", name, counter);
}
class SafeDispose : IDisposable {
public IDisposable child;
public void Dispose() {
if (child != null) { child.Dispose(); child = null; }
}
}
static void safe_using<T>(Func<T> init, Action<T> body) where T : IDisposable {
var sd = new SafeDispose(); // assumed stack optimizationusing (sd) {
T t; try { } finally { t = init(); sd.child = t; }
body(t);
}
}
static void Main(string[] args) {
test("default",() => {
using (var it = new A()) { it.fn(); }
});
test("crutch ", () => {
safe_using(() => new A(), it => { it.fn(); });
});
}
}
Здравствуйте, Shmj, Вы писали:
S>Тут:
S>https://www.youtube.com/watch?v=ns8K-egSLzo
S>Для меня самая боль была — это №3 — проверить реализует ли object obj интерфейс IContract<T>
S>Что у вас на первом месте?
F#
без шуток
приспичило тут веб апи которое отдает файл и после его удаляет
на сатурне сделал не задумываясь через try finally
потом решил перенести код на mvc classic
сколько же там оказалось потребуется сделать приседаний.
for (int i = 0;i < 100;i++) {
var thread = new Thread(() => {
for(;;) action();
});
thread.Start();
thread.Abort();
}
А action в секцию finally перенести не может изб.ежать проблем с Abort? Я просто под никс,
лень на венду переключаться, тут abort не рабоает( System.PlatformNotSupportedException: Thread abort is not supported on this platform.)
Здравствуйте, fdn721, Вы писали:
F>Если где-то в коде есть thread.Abort() — то это перманентный говнокод!
Конечно. Т.к. функцию добавили, а поддержку её на уровне компилятора забыли добавить. И потом если вы не умеете пользоваться костылями — это говнокод. Болле того все будут с пеной у рта доказывать что так и должно быть.
Здравствуйте, Shmj, Вы писали:
S>Для меня самая боль была — это №3 — проверить реализует ли object obj интерфейс IContract<T>
Из перечисленного реальной и серьезной проблемой на практике являются дебильные события. Вот они порой многодневную отладку вызывают, дичайшие костыли и утечки памяти. Остальное мелкие косяки дизайна Шарпа появившиеся в следствие общей необразованности Хельсберг к моменту создания C#. С Тайпскриптом у него уже лучше получилось. Но теперь это все уже вшито не только в дизайн языка, но и во многом в платформу.
Ну и чувак явно не видел Nemerle. Там многие из озвученных им вещей устранены или не сделаны. Вот только "_" есть.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, romangr, Вы писали:
R>Отсутствие нормального функционального типа, в результате делегаты с одинаковой сигнатурой несовместимы между собой.
Орел в видео начал в правильном направлении мыслить и первопричину назвал (дебильные события для которых делегаты создавались). Но обобщить и сказать как надо он не смог.
В целом жить с Func<...> и Action таки можно. После заклёпывания кучи оберточных функций становится вполне комфортно. Так что тоже не такая уж и огромная проблема. Просто кося к в дизайне. Причем не языка, а самого Фреймворка.
А вот от подвисших ссылок на событиях страдает море кода. Главный способ добиться незаметной утечки памяти — это использовать делегат. У нас даже наклепали WeakHandler, который отписывает объекты удерживаемый только подпиской на событие. Но там тоже проблемы есть.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Остальное мелкие косяки дизайна Шарпа появившиеся в следствие общей необразованности Страуструпа к моменту создания C#. С Тайпскриптом у него уже лучше получилось.
Здравствуйте, Shmj, Вы писали: S>Что у вас на первом месте?
Делегаты и события. Фантастически неудачный дизайн.
Нужно было сразу развести их на две разных ветки. То есть дизайн, принятый в Delphi, был вполне удачен.
Напомню тем, кто не застал: там делегаты были single-cast; а если кому-то требовалось использовать множественную обработку одного события, то надо было применять экземпляр специального класса.
В дотнете остались рудименты обсуждений в виде иерархии MulticastDelegate: Delegate, но реально эту двойственность никто так и не реализовал.
Пользы от принудительной мультикастности — нуль, а вреда — много.
Если бы можно было перепроектировать язык c нуля, то события должны были бы быть реализованы совершенно по другому.
Во-первых, подписка должна была бы возвращать IDisposable, диспоз которого бы означал детерминированную отписку. Метод remove (-=) нафиг не нужен.
Во-вторых, семантика вызова события должна зависеть от типа события — в частности, для делегатов с возвращаемым значением надо возвращать не T, а IEnumerable<T>. Это если уж задуряться и пытаться покрыть "самый общий случай". При том, что 99.9% можно было покрыть, принудительно используя EventHandler<T> в качестве основы.
То есть пишем
public eventint CounterChanged; // private EventHandler<int> _counter
И всё — у нас там фен-шуйный мультикаст делегат с сигнатурой void Invoke(object sender, int arg).
Совместимость разноимённых делегатов — фигня, она крайне редко стреляет в реальности, и если вы попали в те 0.000001% случаев, где она реально нужна, она тривиально обходится через d1 + d2.Invoke.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, 4058, Вы писали:
4>Здравствуйте, vaa, Вы писали:
vaa>>Сегодня такой: vaa>>
vaa>> task.RunSynchronously();
vaa>>
vaa>>Вопрос когда это код упадет?
4>Наверно, когда время придёт.
Зависит от того что такое task. Если честно я просто в шоке от плодящихся в C# косяков.
если коротко, то метод async Task Boo() всегда запускается асинхронно,т.е. Boo().RunSynchronously() будет падать.
Но при этом это вполне законная конструкция!
В отличии от F# который крутится на той же платформе, но в разы предсказуемый:
Здравствуйте, vaa, Вы писали:
vaa>Зависит от того что такое task. Если честно я просто в шоке от плодящихся в C# косяков. vaa>если коротко, то метод async Task Boo() всегда запускается асинхронно,т.е. Boo().RunSynchronously() будет падать.
Здравствуйте, Sharov, Вы писали:
S>Здравствуйте, vaa, Вы писали:
vaa>>Зависит от того что такое task. Если честно я просто в шоке от плодящихся в C# косяков. vaa>>если коротко, то метод async Task Boo() всегда запускается асинхронно,т.е. Boo().RunSynchronously() будет падать.
S>Это почему будет падать?
потому что таска уже стартовала в хз каком потоке, а синх вроде бы означает вызывающий поток.