идея переключения / сопоставления с образцом

Я недавно смотрел на 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).

Ответы на вопрос(11)

Ваш ответ на вопрос