Недавно я смотрел F #, и, хотя я вряд ли скоро скачу за ограду, он определенно выделяет некоторые области, где С# (или поддержка библиотеки) может облегчить жизнь.
В частности, я думаю о возможности сопоставления шаблонов F #, что позволяет использовать очень богатый синтаксис - гораздо более выразительный, чем текущий эквивалент С# или условный эквивалент С#. Я не буду пытаться привести прямой пример (мой F # не подходит), но вкратце он позволяет:
- соответствие по типу (с проверкой полного охвата для дискриминационных объединений) [обратите внимание, что это также указывает тип для связанной переменной, предоставляя доступ к члену и т.д.]
- совпадение по предикату
- комбинации вышеуказанных (и, возможно, некоторых других сценариев, о которых я не знаю)
Хотя было бы замечательно, что С# в конечном итоге заимствовал [ах] часть этого богатства, тем временем я смотрел, что можно сделать во время выполнения - например, довольно легко сбить некоторые объекты с позволяют:
var getRentPrice = new Switch<Vehicle, int>()
.Case<Motorcycle>(bike => 100 + bike.Cylinders * 10) // "bike" here is typed as Motorcycle
.Case<Bicycle>(30) // returns a constant
.Case<Car>(car => car.EngineType == EngineType.Diesel, car => 220 + car.Doors * 20)
.Case<Car>(car => car.EngineType == EngineType.Gasoline, car => 200 + car.Doors * 20)
.ElseThrow(); // or could use a Default(...) terminator
где getRentPrice - это Func < Vehicle, int > .
[примечание - возможно, Switch/Case - это неправильные термины... но он показывает идею]
Для меня это намного яснее, чем эквивалент, используя повторяющийся if/else или сложный тернарный условный (который становится очень грязным для нетривиальных выражений - скобки в изобилии). Он также позволяет избежать большого количества кастингов и позволяет простое расширение (прямо или через методы расширения) для более конкретных совпадений, например сравнение InRange (...), сравнимое с выбором VB... Случай "x To y".
Я просто пытаюсь оценить, думают ли люди, что есть много преимуществ от конструкций, подобных приведенным выше (при отсутствии поддержки языка)?
Обратите внимание, что я играл с 3 вариантами выше:
- a Func < TSource, TValue > версия для оценки - сопоставима с составными тернальными условными утверждениями
- Действие <TSource> версия - сопоставима с if/else if/else if/else if/else
- выражение < Func < TSource, TValue → > версия - как первая, но используемая произвольными поставщиками LINQ
Кроме того, использование версии, основанной на выражении, позволяет перезаписывать репрезентацию дерева выражений, существенно вставляя все ветки в единое составное условное выражение, вместо использования повторного вызова. Я недавно не проверял, но в некоторых ранних сборках Entity Framework я, похоже, напоминаю, что это необходимо, так как это не очень понравилось InvocationExpression. Он также позволяет более эффективно использовать LINQ-to-Objects, поскольку он избегает повторных вызовов делегатов - тесты показывают совпадение, подобное приведенному выше (с использованием формы выражения), выполняющееся с одинаковой скоростью [на самом деле быстрее] по сравнению с эквивалентным С# составной условный оператор. Для полноты, Func <... > основанная на версии, заняла в 4 раза длиннее условного оператора С#, но все еще очень быстро и вряд ли станет основным узким местом в большинстве случаев использования.
Я приветствую любые мысли/ввод/критику/и т.д. выше (или о возможностях более богатой поддержки языка С#... здесь надеясь; -p).