Я недавно смотрел на F #, и, хотя я вряд ли скоро пройду через забор, он определенно выделяет некоторые области, где C # (или поддержка библиотеки) может облегчить жизнь.
В частности, я думаю о возможности сопоставления с образцом в F #, которая допускает очень богатый синтаксис - гораздо более выразительный, чем текущие переключатели / условные эквиваленты C #. Я не буду пытаться привести прямой пример (мой F # не подходит), но вкратце это позволяет:
- соответствие по типу (с проверкой полного охвата для различающихся объединений) [обратите внимание, что это также выводит тип для связанной переменной, предоставляя доступ к члену и т. Д.)
- совпадение по предикату
- комбинаций вышеперечисленного (и, возможно, некоторых других сценариев, о которых я не знаю)
Хотя для C # было бы неплохо в конечном итоге позаимствовать [гм] часть этого богатства, в промежутке между тем я смотрел на то, что можно сделать во время выполнения - например, довольно легко собрать вместе несколько объектов, чтобы позволяют:
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 .
[примечание - возможно Switch / Case здесь неправильные термины ... но это показывает идею]
Для меня это намного яснее, чем эквивалент с использованием многократного if / else или составного троичного условного выражения (которое становится очень грязным для нетривиальных выражений - скобки в изобилии). Это также позволяет избежать много приведения и позволяет простое расширение (напрямую или с помощью методов расширения) до более конкретных совпадений, например, совпадение InRange (...), сопоставимое с VB Select .. .Case "x To y".
Я просто пытаюсь оценить, считают ли люди, что конструкции, подобные приведенным выше, приносят большую пользу (при отсутствии языковой поддержки)?
Обратите внимание, что я играл с 3 вариантами выше:
- версия Func для оценки - сопоставимая с составными тройными условными выражениями
- версия Action - сравнимо с if / else if / else if / else if / else
- версия Expression > - как первая, но используемая произвольными поставщиками LINQ
Кроме того, использование версии на основе выражений позволяет переписывать дерево выражений, по существу объединяя все ветви в одно составное условное выражение, а не используя повторный вызов. Я недавно не проверял, но в некоторых ранних сборках Entity Framework я вспоминаю, что это было необходимо, так как ему не очень нравилось InvocationExpression. Он также позволяет более эффективно использовать LINQ-to-Objects, поскольку он избегает повторных вызовов делегатов - тесты показывают совпадение, подобное приведенному выше (с использованием формы выражения), с той же скоростью (на самом деле, немного быстрее) по сравнению с эквивалентным C # составное условное утверждение. Для полноты, основанная на Func <...> версия заняла в 4 раза больше времени, чем условный оператор C #, но все еще очень быстра и вряд ли станет основным узким местом в большинстве случаев использования.
Я приветствую любые мысли / замечания / критические замечания и т. Д. По поводу вышеизложенного (или о возможностях более богатой поддержки языка C # ... надеемся ;-p).