C # как избежать нескольких коммутаторов (делегат?) - PullRequest
2 голосов
/ 23 февраля 2012

Я использую несколько переключателей в моем коде, чтобы отразить выбор вида в списке.Один из них выглядит так:

    private int getOrganelleLength() {
        int species = listBox1.SelectedIndex;

        switch (species) {
            case 0:
                //Console.WriteLine("arabidopsis");
                return 154478;

            case 1:
                //Console.WriteLine("oryza");
                return 134525;

            case 2:
                //Console.WriteLine("glycine");
                return 152218;

            default:
                Console.WriteLine("Error");
                throw new Exception("wrong speices choice");
        }
    }

секунда выглядит следующим образом:

    private int getLengthOfChromosome(int number) {

        int species = listBox1.SelectedIndex;

        switch (species) {
            case 0:
                //Console.WriteLine("arabidopsis");
                return arabidopsis_chromosomes[number - 1];

            case 1:
                //Console.WriteLine("oryza");
                return oryza_chromosomes[number - 1];

            case 2:
                //Console.WriteLine("glycine");
                return glycine_chromosomes[number - 1];

            default:
                Console.WriteLine("Error");
                throw new Exception("wrong speices choice");
        }

Мне почему-то кажется, что это не самое ясное решение, это многократное использование переключателя.Однако обе функции возвращают совершенно разные значения (конечно, на основе выбора вида).Я хотел бы узнать, как улучшить мой код, если есть способ.Большое спасибо.

Ответы [ 4 ]

1 голос
/ 23 февраля 2012

Во-первых, вы должны бросить NotImplementedException в вашем default случае, а не Exception.

Затем вы должны взглянуть на Func<T, TResult> делегат .

Ваш код может выглядеть примерно так:

private int GetInformationAboutSpecies(ListBox listBox, ISwitchCaseResolver helper)
{
    return helper.GetInformation(listBox.SelectedIndex);
}

Затем вы можете реализовать конкретный класс интерфейса ISwitchCaseResolver для каждого вашего вида. Вы также можете использовать шаблон Factory для вызова правильной реализации вашего интерфейса.

1 голос
/ 23 февраля 2012

Посмотрите методы рефакторинга. Это звучит как Заменить условное на полиморфизм

Так что используйте классы для своих объектов данных.

1 голос
/ 23 февраля 2012

Вы можете написать:

private int getOrganelleLength() {
    var dict = new Dictionary<int, int>() { {0, 154478}, {1, 134525}, {2, 152218} };
    return dict[listBox1.SelectedIndex];
}

private int getLengthOfChromosome(int number) {
    var dict = new Dictionary<int, Func<int>>() {
           {0, () => arabidopsis_chromosomes[number - 1]},
           {1, () => oryza_chromosomes[number - 1]}
           {2, () => glycine_chromosomes[number - 1]}}; 
    return dict[listBox1.SelectedIndex]();
 }

В последнем случае вам на самом деле не нужен Func, так как вы можете просто добавить в словарь значения arabidopsis_chromosomes, написав это еще для примера.

В любом случае, это будет работать, только если у вас очень простой переключатель. Если вам нужно написать что-то более сложное, не используйте его. В этом случае вам следует реорганизовать свой код и использовать полиморфизм и фабрики.

1 голос
/ 23 февраля 2012

Полагаю, arabidopsis_chromosomes и др. Являются массивами или списками.

Просто добавьте их в массив или список.

Например (очень упрощенно):

object[][] foo = {{ 1,2,3}, {4,5,6}};

object Get(int x, int y)
{
  return foo[x][y];
}
...