Onur ERYILMAZ Ответов: 4

Как избавиться от цепочки if-else?


Привет,

В настоящее время я работаю над приложением Winforms. У меня есть база данных, и в ней есть таблицы.

Я создал форму, которая отвечает за отображение данных, поступающих из этих таблиц данных. Для этого я добавил в эту форму элемент управления представлением Таблицы данных. Я также создал "перечисление", чтобы указать, какие данные отображаются. Форма получает данные из базы данных и отображает их в виде таблицы данных.

Но у меня есть некоторые проблемы об этом.

У меня есть много разных данных, чтобы показать,и поэтому у меня есть много цепочек if-else. Нравится;
if(listType == ListViewTypes.Accounts)
{ 
   //get data from database
} else if(listType == ListViewTypes.Persons)
{ 
  // get data from database
} 
//etc...


Есть ли какое-то решение по этому поводу?

Спасибо.

Что я уже пробовал:

Я думаю о создании другого класса, чтобы справиться с этим, но я также использую эту цепочку if-else в этом классе.

CHill60

Я немного опоздал на вечеринку, но, заметив решение, которое вы приняли, вы можете найти эту статью полезной Диспетчер Динамических Методов[^]

4 Ответов

Рейтинг:
2

OriginalGriff

Используйте переключатель:

switch (listType)
   {
   case ListViewTypes.Accounts:
      ...
      break;
   case ListViewTypes.Persons:
      ...
      break;
...
   default:
      ...
      break;
   }


Рейтинг:
2

CPallini

В зависимости от однородности выполняемого кода Вы можете использовать Dictionary от delegates. см., например: c# - словарь с делегатом или переключателем? - переполнение стека[^].


Рейтинг:
2

Sascha Lefèvre

В качестве альтернативы решению 1( что совершенно нормально): вы также можете использовать словарь для сопоставления делегатов с вашими "типами списков". Я предпочитаю делать это вместо оператора switch, если операторы case станут довольно длинными. Пример (который использует составленные типы):

class Program
{
    static void Main(string[] args)
    {
        Demo demo = new Demo();

        string action = "multiplyBy3";
        int input = 1;

        int result = demo.DoSomething(action, input);
    }

    class Demo
    {
        static Dictionary<string, Func<int, int>> Actions = new Dictionary<string, Func<int, int>>()
        {
            { "multiplyBy2", x => x * 2 },
            { "multiplyBy3", x => MultiplyBy3(x) },
        };

        public int DoSomething(string action, int input)
        {
            return Actions[action](input);
        }

        static int MultiplyBy3(int input)
        {
            return input * 3;
        }
    }
}


Рейтинг:
19

F-ES Sitecore

Вы можете переместить оператор "if" в фабричный класс

public interface IDataHandler
{
    void PopulateGridView(GridView gridView);
}

public class AccountsHandler : IDataHandler
{
    public void PopulateGridView(GridView gridView)
    {
        // populate gridView with accounts
    }
}

public class PersonsHandler : IDataHandler
{
    public void PopulateGridView(GridView gridView)
    {
        // populate gridView with people
    }
}

public class DataHandlerFactory
{
    public IDataHandler GetDataHandler (ListViewTypes types)
    {
        switch(types)
        {
            case ListViewTypes.Accounts:
                return new AccountsHandler();
            case ListViewTypes.Persons:
                return new PersonsHandler();
            default:
                throw new NotImplementedException();
        }
    }
}


использование

DataHandlerFactory f = new DataHandlerFactory();

IDataHandler dh = f.GetDataHandler(types);

dh.PopulateGridView(GridView1);


Вы даже можете сделать что-то вроде этого, чтобы избавиться от переключателя

public class DataHandlerFactory
{
    private static Dictionary<ListViewTypes, IDataHandler> handlers;

    static DataHandlerFactory()
    {
        handlers = new Dictionary<ListViewTypes, IDataHandler>();

        handlers.Add(ListViewTypes.Accounts, new AccountsHandler());
        handlers.Add(ListViewTypes.Persons, new PersonsHandler());
    }

    public IDataHandler GetDataHandler (ListViewTypes types)
    {
        IDataHandler dh;
            
        if (!handlers.TryGetValue(types, out dh))
        {
            throw new NotImplementedException();
        }

        return dh;

    }
}


Onur ERYILMAZ

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

Onur ERYILMAZ

Хорошо, я внедрил его в свой проект, но, к сожалению, возникает еще одна проблема.
Допустим, у меня есть таблица данных в моей базе данных, которая хранит информацию об идентификаторах, именах и фамилиях людей, и у меня есть еще одна таблица, которая хранит идентификатор и номер телефона людей.
В моем перечислении ListViewTypes у меня есть такие перечисления, как Persons и PersonsWithPhoneNumbers.
Таким образом, класс PersonsHandler может обрабатывать извлечение данных только из одной таблицы данных, но когда мне нужен человек с телефонными номерами, я должен создать другой класс PersonHandlerWithPhoneNumbers. Что meaningles я вещь.

Я могу добавить в IDataHandler еще один метод, например PopulateGridViewWithExtraInformation. Но в этом случае я должен добавить этот метод ко всем обработчикам, и это тоже бессмысленно.

Что бы вы предложили, чтобы справиться с подобными ситуациями?

Спасибо.

F-ES Sitecore

Вы всегда можете передать оба вида сетки в метод

общественного недействительными PopulateGridView(GridView в gridViewPrimary, GridView в gridSecondary)

затем каждая реализация IDataHandler может решить, используется ли вторичная или нет

Onur ERYILMAZ

Но у моей формы есть только один вид сетки.

F-ES Sitecore

Так в чем же тогда проблема? Показывает ли он различные типы данных в одном сеточном представлении? Если это так, то вы, вероятно, можете использовать вложенные представления сетки, так что данные телефона будут представлять собой ячейку, которая является другим представлением сетки, или что-то в этом роде.