Eu estive analisando o F # recentemente e, embora não seja provável que pule a barreira tão cedo, ele definitivamente destaca algumas áreas em que o C # (ou o suporte de biblioteca) poderia facilitar a vida.
Em particular, estou pensando no recurso de correspondência de padrões do F #, que permite uma sintaxe muito rica - muito mais expressiva do que os atuais comutadores / equivalentes em C # condicionais. Não tentarei dar um exemplo direto (meu F # não depende dele), mas, em suma, ele permite:
- corresponder por tipo (com verificação de cobertura total para uniões discriminadas) [observe que isso também infere o tipo da variável vinculada, fornecendo acesso a membros etc.]
- combinar por predicado
- combinações dos itens acima (e possivelmente de outros cenários dos quais não conheço)
Embora seja adorável o C # eventualmente emprestar [ahem] parte dessa riqueza, nesse meio tempo, eu estive analisando o que pode ser feito em tempo de execução - por exemplo, é bastante fácil reunir alguns objetos para permitir:
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
onde getRentPrice é um Func <Vehicle, int>.
[nota - talvez Switch / Case tenha os termos errados ... mas mostra a ideia]
Para mim, isso é muito mais claro que o equivalente, usando if / else repetido ou uma condicional ternária composta (que fica muito confusa para expressões não triviais - colchetes em abundância). Ele também evita muitas transmissões e permite uma extensão simples (diretamente ou por meio de métodos de extensão) para correspondências mais específicas, por exemplo, uma correspondência InRange (...) comparável à VB Select ... Case "x To y "uso.
Estou apenas tentando avaliar se as pessoas pensam que há muitos benefícios em construções como as mencionadas acima (na ausência de suporte ao idioma)?
Observe também que eu tenho jogado com 3 variantes do acima:
- uma versão Func <TSource, TValue> para avaliação - comparável a declarações condicionais ternárias compostas
- uma versão Action <TSource> - comparável a if / else if / else if / else if / else
- uma versão Expression <Func <TSource, TValue >> - como a primeira, mas utilizável por provedores arbitrários de LINQ
Além disso, o uso da versão baseada em expressão permite reescrever a árvore de expressões, essencialmente incorporando todas as ramificações em uma única expressão condicional composta, em vez de usar a chamada repetida. Não verifiquei recentemente, mas em algumas versões anteriores do Entity Framework, lembro que isso era necessário, pois não gostava muito de InvocationExpression. Ele também permite um uso mais eficiente com o LINQ-to-Objects, uma vez que evita repetidas invocações de delegados - os testes mostram uma correspondência como a acima (usando o formulário Expressão) com a mesma velocidade [marginalmente mais rápida, na verdade] em comparação com o equivalente em C # declaração condicional composta. Para ser completo, a versão baseada em Func demorou quatro vezes mais que a instrução condicional C #, mas ainda é muito rápida e dificilmente será um grande gargalo na maioria dos casos de uso.
Congratulo-me com quaisquer pensamentos / sugestões / críticas / etc sobre o que foi dito acima (ou sobre as possibilidades de um suporte mais avançado à linguagem C # ... aqui está a esperança ;-p).
switch-case
declaração. Não me interpretem mal, acho que tem o seu lugar e provavelmente procurarei uma maneira de implementar.