Всё верно. Как я понял, дополнительные скобочки нужны только для того, чтобы объединять параметры, если есть перегрузка, которая принимает несколько аргументов: тык
Ввели бы pending на пару кадров, считая предыдущее время рендеринга кадров, и при единичных отклонениях игнорируя текущее и брать предыдущие. Тогда проблема с единичными задержками бы полечилась (то есть если период в «кардиограмме» достаточно большой, то в чём вообще беда?)
Чего действительно не хватает лично мне — это using на «стеке». Хочется избавиться от лишней вложенности, когда у вас есть несколько IDisposable-объектов, которые захватываются в методе, и это полотно из using-ов выглядит некрасиво и многословно. Если бы сделали конструкцию вида
using var recource = CreateDisposable();
Которая бы автоматически открывала using и закрывала его при уходе переменной из области видимости — было бы великолепно. Кажется, когда-то на гитхабе в репозитории Roslyn видел в issues подобный proposal, но с ним что-то было не так. Хотя в C++/CLI такой синтаксис есть и все проблемы решить смогли.
Выглядит красиво, пока мы не вспоминаем про многозадачное окружение – как быть там в случае, если кто-то вклинился между проверкой и использованием?
Вот тут с переводчиком не соглашусь. Это вовсе не та проблема, которую пытаются решать. Этот синтаксис должен решать только проблему контракта, и какой-никакой автоматической его проверки (точнее это должны делать анализаторы). Этот синтаксис не будет сам осуществлять никаких проверок и он не защитит вас от NRE, в откомпилированном коде вообще не будет разницы, писали вы «MyClass?» или «MyClass» (возможно только метаинформация с аттрибутами).
Это конечно хорошо, но объясните, чем конкретно в этом юзкейсе и для ваших агрументов не подходит extension-метод?
Тут можно парировать тем, что вдруг мы на логирование исключений захотим делать какие-то дополнительные действия, но конкретно в этом случае это звучит все равно странно, потому что делать что-то ещё — явно не зона ответственности логера.
Именно так, тоже хотел об этом написать, можно добавить ключевое слово interface хоть в С++, оставив множественное наследование (если бы не проблема с виртуальными деструкторами).
Проблема с виртуальным деструктором тоже решаема, но это тема для отдельной дискуссии, уходящей в итоге в наличие «object» в языке.
так вот он абстрактные классы, не имеющие полей, реализует именно как интерфейсы
Отлично! Это то, что и нужно, чтобы называться интерфейсом. А теперь давайте в идельном мире закрепим это явно на уровне языка, чтобы это происходило всегда по спецификации, а когда не происходило — не компилировалось. И вот мы получаем ключевое слово interface.
Я правильно понимаю, что человек лезет изменять контракты и не знает, как они работают?
Нет, речь не про это, эти изменения можно осуществить без изменения контракта.
Сужая возможности язык вынуждает писать больше кода
Мы же вроде бы с вами говорим о случае, когда вы хотите именно интерфейс, но вместо этого используете абстрактный класс со всеми чисто виртуальными методами? Как гарантия того, что интерфейс останется интерфейсом вынудит писать вас больше кода?
Да, я с вами согласен, что в случае, когда у вас есть класс, в котором все методы чисто виртуальные — эта синтаксическая конструкция эквивалентна интерфейсу.
Но есть одно «но». Никто вам не гарантирует, что завтра какой-нибудь абстрактный програмист не решит добавить в этот базовый абстрактный класс маленький флажочек/кэш, и тогда код скомпилируется, но если где-то упаси боже (увидел, что вы C#/C++ разработчик), при маршалинге из нативных плюсов в Managed-мир вы решите кастануть указатель к IntPtr, а потом где-то обратно передать в нативный мир, кастанув к указателю на базовый класс, то this поедет и код будет мазать по памяти (понятно, что это легко решается типизацией IntPtr до какого-то своего типа в managed-мире, но всё же).
Пример, конечно, надуманный, но я хочу донести то, что ЯП предоставляет гарантии и уменьшает количество способов стрельнуть в ногу. И понятие интерфейса в том же самом С++ дало бы гарантию того, что в этой сущности не может быть состояния.
Не знаю, насколько точную я аналогию смогу привести, но интерфейс — это принципиальная схема какого-то устройства, а абстрактный класс — это, если хотите, печатная плата, в которую надо впаять нужные детали.
Если говорить в терминах С++, то эта «плата» — таблица виртуальных функций. Если объект унаследован от N абстрактных классов, то, в зависимости от того, под каким из N типов вы на него смотрите, this сможет принимать до N+1 значения. В случае с интерфейсами — это один объект, который реализует N интерфейсов и this там одинаковый. Учитывая то, что мы захотим виртуальный деструктор — вот вам и пачка смешений.
Например, если посмотреть на __declspec(interface), то он подразумевает под собой novtable, из-за чего мы не можем удалить объект по указателю на интерфейс.
— Правда? А что такое интерфейс? Это то же самое что и класс?
— Ну… Не совсем!
— В каком плане? — Не один из его методов не должен иметь реализации.
Очень уж мне не нравится это определение интерфейса. Лично для себя сформулировал, что интерфейс — это описание контракта, и это не класс со всеми методами без реализаций. Это разные сущности, в том-же C# можно явно реализовать интерфейс, попробуйте сделать то же самое с абстрактным классом.
Перешёл на Яндекс.Браузер только чтобы опробовать Ваш «Дзен». Штука довольно интересная, достаточно точно определила мои интересы без каких-либо первоначальных настроек с моей стороны. Но всё же, одна и та же новость всплывает со многих ресурсов по десять, а то и больше раз. Так уж получилось, что новость про «Android запустили на iPhone» (не запустили) мне была показана уже раз 15. Ваши Яндекс.Новости отлично умеют собирать информацию с кучи источников и формировать в отдельные сюжеты. Нельзя ли применить подобную технологию для того, чтобы пользователи на сталкивались с вышеописанной проблемой?
Всё верно. Как я понял, дополнительные скобочки нужны только для того, чтобы объединять параметры, если есть перегрузка, которая принимает несколько аргументов: тык
Которая бы автоматически открывала using и закрывала его при уходе переменной из области видимости — было бы великолепно. Кажется, когда-то на гитхабе в репозитории Roslyn видел в issues подобный proposal, но с ним что-то было не так. Хотя в C++/CLI такой синтаксис есть и все проблемы решить смогли.
Вот тут с переводчиком не соглашусь. Это вовсе не та проблема, которую пытаются решать. Этот синтаксис должен решать только проблему контракта, и какой-никакой автоматической его проверки (точнее это должны делать анализаторы). Этот синтаксис не будет сам осуществлять никаких проверок и он не защитит вас от NRE, в откомпилированном коде вообще не будет разницы, писали вы «MyClass?» или «MyClass» (возможно только метаинформация с аттрибутами).
Тут можно парировать тем, что вдруг мы на логирование исключений захотим делать какие-то дополнительные действия, но конкретно в этом случае это звучит все равно странно, потому что делать что-то ещё — явно не зона ответственности логера.
Проблема с виртуальным деструктором тоже решаема, но это тема для отдельной дискуссии, уходящей в итоге в наличие «object» в языке.
Нет, речь не про это, эти изменения можно осуществить без изменения контракта.
Мы же вроде бы с вами говорим о случае, когда вы хотите именно интерфейс, но вместо этого используете абстрактный класс со всеми чисто виртуальными методами? Как гарантия того, что интерфейс останется интерфейсом вынудит писать вас больше кода?
Но есть одно «но». Никто вам не гарантирует, что завтра какой-нибудь абстрактный програмист не решит добавить в этот базовый абстрактный класс маленький флажочек/кэш, и тогда код скомпилируется, но если где-то упаси боже (увидел, что вы C#/C++ разработчик), при маршалинге из нативных плюсов в Managed-мир вы решите кастануть указатель к IntPtr, а потом где-то обратно передать в нативный мир, кастанув к указателю на базовый класс, то this поедет и код будет мазать по памяти (понятно, что это легко решается типизацией IntPtr до какого-то своего типа в managed-мире, но всё же).
Пример, конечно, надуманный, но я хочу донести то, что ЯП предоставляет гарантии и уменьшает количество способов стрельнуть в ногу. И понятие интерфейса в том же самом С++ дало бы гарантию того, что в этой сущности не может быть состояния.
Если говорить в терминах С++, то эта «плата» — таблица виртуальных функций. Если объект унаследован от N абстрактных классов, то, в зависимости от того, под каким из N типов вы на него смотрите, this сможет принимать до N+1 значения. В случае с интерфейсами — это один объект, который реализует N интерфейсов и this там одинаковый. Учитывая то, что мы захотим виртуальный деструктор — вот вам и пачка смешений.
Например, если посмотреть на __declspec(interface), то он подразумевает под собой novtable, из-за чего мы не можем удалить объект по указателю на интерфейс.
Очень уж мне не нравится это определение интерфейса. Лично для себя сформулировал, что интерфейс — это описание контракта, и это не класс со всеми методами без реализаций. Это разные сущности, в том-же C# можно явно реализовать интерфейс, попробуйте сделать то же самое с абстрактным классом.
Причём после каждого Win-L + разблокировки добавляется по одному зомби.