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