operatore per enumerazioni
-
20-09-2019 - |
Domanda
Solo per curiosità, chiedo questo
Come l'espressione qui sotto
a = (condition) ? x : y; // two outputs
perché non possiamo avere un operatore per le enumerazioni?
Dire,
myValue = f ??? fnApple() : fnMango() : fnOrange(); // no. of outputs specified in the enum definition
invece delle istruzioni switch (anche se il refactoring è possibile)
enum Fruit
{
apple,
mango,
orange
};
Fruit f = Fruit.apple;
O è una specie di operatore inutile?
Soluzione
Non posso dire di aver mai desiderato un operatore del genere, che sarebbe incredibilmente fragile facendo affidamento sull'ordinamento dei valori enum.Puoi facilmente utilizzare un interruttore:
switch (f)
{
case Fruit.Apple: myValue = fnApple(); break;
case Fruit.Mango: myValue = fnMango(); break;
case Fruit.Orange: myValue = fnOrange(); break;
default: throw new ArgumentOutOfRangeException("f");
}
In alternativa, crea una mappa:
static readonly Dictionary<Fruit, Func<Foo>> FruitFunctions =
new Dictionary<Fruit, Func<Foo>> {
{ Fruit.Apple, fnApple },
{ Fruit.Mango, fnMango },
{ Fruit.Orange, fnOrange }
};
...
myValue = FruitFunctions[f]();
Ho usato entrambe le tecniche in varie situazioni e, temo, le preferisco di gran lunga all'operatore suggerito.
Altri suggerimenti
A prima vista posso pensare a tre ragioni:
- È fragile.Se qualcuno decide di riordinare l'enumerazione, ti ritroverai con la chiamata delle funzioni sbagliate.
- Non è ovvio.Non riesco a capire quale funzione verrà eseguita in tal caso senza passare alla definizione dell'enumerazione e verificare in quale ordine si trovano le enumerazioni.
- Ogni funzionalità inizia con meno 100 punti. È improbabile che qualcosa del genere giustifichi lo sforzo richiesto per specificarlo, costruirlo, documentarlo e testarlo, soprattutto se confrontato con altre funzionalità, e soprattutto soprattutto quando esiste già un'alternativa altamente valida nella lingua.
C# prende in prestito la sintassi da C++ e C++ prende in prestito la sintassi da C e C non aveva un ???:::
operatore, perché K&R probabilmente non lo riteneva necessario.Non è un "operatore inutile", ma sarebbe considerato zucchero sintattico.
Inoltre, non è una buona idea per un operatore fare affidamento sul particolare ordine delle costanti nella dichiarazione enum.
la condizione viene valutata come vera o falsa.Qual è l'algoritmo proposto dal tuo operatore inesistente?È difficile dire se possa essere utile o meno, ma switch-case può fare ciò di cui hai bisogno.
Il problema principale - a parte il fatto che è pericoloso, non necessario e probabilmente illeggibile nella maggior parte dei casi reali - è che promuove un modello di programmazione che la maggior parte delle persone oggigiorno considererebbe pessimo.
La maggior parte dei linguaggi ha stili di programmazione/progettazione che consente e quelli che desidera promuovere.C# consente la programmazione imperativa e procedurale ma promuove l'uso di tecniche orientate agli oggetti.Il tuo operatore appartiene saldamente al primo campo e non è qualcosa che i progettisti del linguaggio vorrebbero supportare.
Se volessi programmare in quello stile allora potresti usare:
myValue = (f == Fruit.apple) ? fnApple()
: (f == Fruit.mango) ? fnMango()
: fnOrange();