In fact the command switch-case is enough ugly and almost always expendable.
Instead of using this command or long chains of if-elseif-elseif..., you can use dictionaries.
In your case, you would fill a dictionary of dictionaries, with the following semantics:
profissão -> site -> profissão naquele site
So instead of making a long, confusing, ugly, hard-to-maintain imperative code like this:
switch (profissao_selecionada)
{
case "Engenheiro(a)":
switch (site_selecionado)
{
case "site A":
profissao_no_outro_site = "Engenheiro/Arquiteto";
break;
case "site B":
profissao_no_outro_site = "Engenheiro (outros)";
break;
}
break;
case "Astronauta":
switch (site_selecionado)
{
case "site A":
profissao_no_outro_site = "Cosmonauta";
break;
case "site B":
profissao_no_outro_site = "Espaçonauta";
break;
}
break;
}
you can associate profession and site in a more declarative way:
profissoes["Engenheiro(a)"]["site A"] = "Engenheiro/Arquiteto";
profissoes["Engenheiro(a)"]["site B"] = "Engenheiro (outros)";
profissoes["Astronauta"]["site A"] = "Cosmonauta";
profissoes["Astronauta"]["site B"] = "Espaçonauta";
And then, in just one line, without any switch-case, you check how the profession selected in the combo is defined on a particular site, more or less like this:
profissao_no_outro_site = profissoes[profissao_selecionada][site_selecionado];
Note that you can use the dictionary itself to popular the professions in the combo instead of replicating them in the combo and code, so as to maintain items in one place.
Full example
If you have any questions, see this full functional example:
public partial class Form1 : Form
{
Dictionary<String, Dictionary<String, String>> profissoes;
public Form1()
{
InitializeComponent();
var engenheiro = new Dictionary<String, String>();
engenheiro["site A"] = "Engenheiro";
engenheiro["site B"] = "Engenheiro (outros)";
engenheiro["site C"] = "Engenheiro(a)/Arquiteto(a)";
var astronauta = new Dictionary<String, String>();
astronauta["site A"] = "Cosmonauta";
astronauta["site B"] = "Espaçonauta";
astronauta["site C"] = "Lunático";
profissoes = new Dictionary<String, Dictionary<String, String>>();
profissoes["Engenheiro(a)"] = engenheiro;
profissoes["Astronauto(a)"] = astronauta;
}
private void Form1_Load(object sender, EventArgs e)
{
foreach (var profissao in profissoes)
comboProfissoes.Items.Add(profissao.Key);
}
private void seleciona_Click(object sender, EventArgs e)
{
var profissaoSelecionada = (String)comboProfissoes.SelectedItem;
var mensagem = "A profissão " + profissaoSelecionada
+ " no site B é " + profissoes[profissaoSelecionada]["site B"];
MessageBox.Show(mensagem);
}
}
Whose "output" looks like this:
Storing complex code in the dictionary
And if in every block marry you needed to run some lines of code instead of simply setting a variable like I did in the above example? The dictionary is still the solution!
In the example above, we use the dictionary to store the profession legend on another site, but we can use it to store any object and not just strings. That is, we can add blocks of code in the dictionary to be executed at the right time, dispensing the switch-case in virtually any situation.
Since the dictionary supports objects and almost everything in C# is an object, there are several ways to store code blocks in the dictionary: you can store actions, functions, can define your own delegates, interfaces, abstract classes... The sky is the limit :D
Note that the dictionary key itself can also be any object, further exposing the horizons.
A small example
Let’s assume that same block switch from above do more than just set a variable:
switch (profissao_selecionada)
{
case "Engenheiro(a)":
switch (site_selecionado)
{
case "site A":
// faz um trabalho muito específico aqui
break;
case "site B":
// faz outro trabalho específico aqui
break;
}
break;
case "Astronauta":
switch (site_selecionado)
{
case "site A":
// mais trabalhos complexos
break;
case "site B":
// outros serviços impensáveis
break;
}
break;
}
What you have to do is to encapsulate each code block in methods with a common signature:
void Metodo_01()
{
// faz um trabalho muito específico aqui
}
void Metodo_02()
{
// faz outro trabalho específico aqui
}
void Metodo_03()
{
// mais trabalhos complexos
}
void Metodo_04()
{
// outros serviços impensáveis
}
Hence you declare a delegate with this common signature (or uses the native . Net delegates, if you prefer):
delegate void ProcessadorProfissoes();
And then fill in the dictionary as before, only now adding methods to it instead of adding strings:
var processadorEngenheiro = new Dictionary<String, ProcessadorProfissoes>();
processadorEngenheiro["site A"] = Metodo_01;
processadorEngenheiro["site B"] = Metodo_02;
var processadorAstronauta = new Dictionary<String, ProcessadorProfissoes>();
processadorAstronauta["site A"] = Metodo_03;
processadorAstronauta["site B"] = Metodo_04;
processadorProfissoes = new Dictionary<string,Dictionary<string, ProcessadorProfissoes>>();
processadorProfissoes["Engenheiro(a)"] = processadorEngenheiro;
processadorProfissoes["Astronauta"] = processadorAstronauta;
Now, to run the code block referring to the selected profession and site, just this simple line, without switch-case, without if...:
processadorProfissoes[profissaoSelecionada][siteSelecionado]();
Completion
Block code switch-case and long blocks if-If if most often can be better expressed through dictionaries or combination of dictionaries, simplifying code maintenance.
In the examples of this answer, strings and simple-signature methods have been stored in the dictionary; but we can store any type of object, so we can have methods with complex signatures, returning values, or full state-filled objects to perform complex jobs.
What kind of alternative do you want? What’s your problem? You’re just finding it ugly?
– Maniero
if I have to, I extracted the code for functions
– Tiago Bértolo
I fixed the Need ( do ) a :)
– Marco Souza
The problem is basically being ugly. I just put an example because the real code is VERY MUCH bigger. Do it is not so laborious because I was riding the
switch..case
with regex, but reading it and maintenance is very bad. Registering everything in a bank would be an alternative, but the values will hardly change and access to the bank would slow down. Maybe you just don’t have a choice And I’ll have to live with that :(– Daniel Dutra
I think the best way is to extract each secondary switch for a more generic function, is that it depends a lot on the case, with luck and some abstraction you can even use this function again, but it is very vague your question so there is no way to help you more than that. I’m sorry.
– Guilherme Golfetto
The
switch()
internal to thecase "A":
shall be the same as in case "B":?– Randrade
Yes, @Randrade os
switch
internal may be the same. I put more explanation at the end of the question speaking my real use, I hope it helps.– Daniel Dutra
In this case, you can create a method that receives the value of
var2
and returns the expected value. You will pass this method in eachswitch
, but for maintenance will be much better.– Randrade