Comments 29
И, как же слух режет… :) Интересно, сколько ещё людей слышат букву «Т» в слове feature?
Ну и будем надеяться что это поправят.
.NET очевидно это тупикновая технология, пока были популярны десктопные приложения под Windows она еще как то жила. А сейчас во времена web и смартфонов, учитывая что Windows Phone уже мертвая а главная фишка CLR- кроссплатформенность оказалась не по зубам Микрософту, только неопытный студент захочет использовать тот же .Net Core в продакшене...
Я бы не был столь категоричен учитывая сколько денег и усилий Microsoft сейчас вбухивает в .Net и конкретно в попытки сделать его кроссплатформеным. У меня вообще такое ощущение что они решили "задавить массой".
— Итак, господа, пришло время выбрать технологический стэк для нового проекта
— Конечно же .Net, в него больше денег вбухано!
Вы так себе это представляете?
Ну если вы выбираете стэк на ближайшие 5-10-15 лет, то при прочих равных на мой взгляд всё таки логичнее выбирать стэк, который будет больше развиваться и поддерживаться. И в который инвестируют.
И кроме того есть как минимум вероятность, что фреймворки на C# позволят в будущем целиком покрыть достаточно большие "экосистемы". То есть вам нужен будет всего один язык програмирования для бэкенда/фронтенда в вебе, десктопа под разные ОС и мобильных приложений.
Хотя это всё тоже вилами по воде написано, особенно если вспомнить тот же Silverlight.
А задекларить в switch true?)
switch (true)
{
case signal==Signal.Red ll signal==Signal.Yellow:
int ExecFull(Operation operation, int x, int y)
{
switch (operation)
{
case Operation.Summ:
logger.LogTrace("{x} + {y}", x, y);
return x + y;
case Operation.Diff:
logger.LogTrace("{x} - {y}", x, y);
return x - y;
case Operation.Mult:
logger.LogTrace("{x} * {y}", x, y);
return x * y;
case Operation.Div:
logger.LogTrace("{x} / {y}", x, y);
return x / y;
default:
throw new NotSupportedException();
}
}
Можно написать:
int ExecFull(Operation operation, int x, int y)
{
return operation switch
{
Operation.Summ => Log("{x} + {y}", x, y) ?? x + y;
Operation.Diff => Log("{x} - {y}", x, y) ?? x - y;
Operation.Mult => Log("{x} * {y}", x, y) ?? x * y;
Operation.Div => Log("{x} / {y}", x, y) ?? x / y;
_ => throw new NotSupportedException();
};
static int? Log(...)
{
// log someting
return null;
}
}
К сожалению, в большом проекте у этого способа есть серьезный недостаток: никто не гарантирует отслеживание в design time расширения Ваших алгебраических типов.
Можно делать "закрытые" иерархии при помощи вложенных типов:
public abstract class Adt
{
public sealed class Case1 : Adt
{
}
public sealed class Case2 : Adt
{
}
private Adt()
{
}
}
Это один вариантов, во что превращаются алгебраические типы данных в F# в скомпилированных сборках.
Видимо, я немного не понял изначальный посыл. Мне показалось, что речь была не столько про exhaustive match, сколько про неожиданное появление новых вариантов в АТД (например, другими людьми).
А так да, для исчерпывающего сравнения только делать вложенные классы private и городить визитор. Для простых случаев, правда, можно обойтись чем-то вроде
public abstract T Match<T>(T case1, T case2);
Но это уже скорее "исчерпывающее сопоставление enum`а".
Как я провел лето с C# 8