switch убрать.
От: Аноним  
Дата: 11.06.13 10:49
Оценка:
Здравствуйте, у меня очень простой вопрос(мне думается). Создал класс, а нем метод(см. ниже). Каким образом можно избавиться от switch. Вроде бы так делать не желательно, это же ООП язык и нужно применять, что то более грамотное(полиморфизм и все что с этим связано). Если количество выборок увеличится, то switch станет ну очень неприятным. Есть ли общепринятые методики для таких вот фрагментов?
public void Check_files(string inFile)
        {
            switch (inFile)
            {
                case "txt":
                     ParseTXT();                    
                    break;
                case "conf":
                    ParseConf();
                    break;
                case "log":
                    ParseLog();
                    break; 
                default:
                    CallBacky.callbackEventHandler("Неверный параметр\n");
                    break;
            }
            
        }


С уважением.
Re: switch убрать.
От: Aen Sidhe Россия Просто блог
Дата: 11.06.13 10:59
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, у меня очень простой вопрос(мне думается). Создал класс, а нем метод(см. ниже). Каким образом можно избавиться от switch. Вроде бы так делать не желательно, это же ООП язык и нужно применять, что то более грамотное(полиморфизм и все что с этим связано). Если количество выборок увеличится, то switch станет ну очень неприятным. Есть ли общепринятые методики для таких вот фрагментов?

А>
private Dictionary<string, Action> _d = new Dictionary<string, Action>
{
         { "txt", ParseTXT },
......
}
А>public void Check_files(string inFile)
А>        {
А>              Action actor;
                if(_d.TryGetValue(nFile, out actor))
                     actor();
                else
                    // не нашли
А>        }
А>


А>С уважением.
С уважением, Анатолий Попов.
ICQ: 995-908
Re: switch убрать.
От: Ilinichev  
Дата: 11.06.13 11:00
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, у меня очень простой вопрос(мне думается). Создал класс, а нем метод(см. ниже). Каким образом можно избавиться от switch. Вроде бы так делать не желательно, это же ООП язык и нужно применять, что то более грамотное(полиморфизм и все что с этим связано). Если количество выборок увеличится, то switch станет ну очень неприятным. Есть ли общепринятые методики для таких вот фрагментов?


Какое такое ООП?

using System;
using System.Reflection;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var str = new string[] { "txt", "conf", "TXT" };

            foreach (var s in str)
            {
                Parse(s);
            }
        }

        static void Parse(string s)
        {
            var bindingFlags = BindingFlags.Static | BindingFlags.InvokeMethod | BindingFlags.IgnoreCase | BindingFlags.NonPublic;

            typeof(Program).InvokeMember("Parse" + s, bindingFlags, null, null, null);
        }

        static void ParseTxt()
        {
            Console.WriteLine("ParseTxt");
        }

        static void ParseConf()
        {
            Console.WriteLine("ParseConf");
        }
    }
}
Re[2]: switch убрать.
От: Ilinichev  
Дата: 11.06.13 11:01
Оценка:
Здравствуйте, Aen Sidhe, Вы писали:

AS>private Dictionary<string, Action> _d = new Dictionary<string, Action>
AS>{
AS>         { "txt", ParseTXT },
AS>......
AS>}


Насколько оправдано здесь применение такой тяжелой структуры данных как Dictionary?
Re: switch убрать.
От: Doc Россия http://andrey.moveax.ru
Дата: 11.06.13 11:12
Оценка: 1 (1)
Здравствуйте, Аноним, Вы писали:

Для 3-5 вариантов не вижу ничего плохого в switch. А вот если больше можно сделать что-то вроде:

Объявить в классе
private readonly Dictionary<string, Action> _actionList;


В конструкторе
this._actionList = new Dictionary<string, Action>() {
    {"txt", this.ProcessTxt},
    {"conf", this.ProcessConf},
    {"log", this.ProcessLog},
};


Ну и использование:
Action action;

if (this._actionsList.TryGetValue(fileType, out action))
    action();
else 
    this.DefaultAction();
Re[3]: switch убрать.
От: Doc Россия http://andrey.moveax.ru
Дата: 11.06.13 11:15
Оценка:
Здравствуйте, Ilinichev, Вы писали:

I>Насколько оправдано здесь применение такой тяжелой структуры данных как Dictionary?


Извините что вопросом на вопрос, но чем лучше использовать Reflection, причем еще обременять класс неявным соглашением об именовании методов.
Re: switch убрать.
От: akasoft Россия  
Дата: 11.06.13 11:15
Оценка: 1 (1) +2
Здравствуйте, <Аноним>, Вы писали:

А>Здравствуйте, у меня очень простой вопрос(мне думается). Создал класс, а нем метод(см. ниже). Каким образом можно избавиться от switch.


А зачем?

А> Вроде бы так делать не желательно, это же ООП язык и нужно применять, что то более грамотное(полиморфизм и все что с этим связано). Если количество выборок увеличится, то switch станет ну очень неприятным.


И что? Что именно не нравится?
... << RSDN@Home 1.2.0 alpha 5 rev. 66>>
Re[2]: switch убрать.
От: 0x7be СССР  
Дата: 11.06.13 11:15
Оценка: +2
Здравствуйте, Ilinichev, Вы писали:


I>
I>        static void Parse(string s)
I>        {
I>            var bindingFlags = BindingFlags.Static | BindingFlags.InvokeMethod | BindingFlags.IgnoreCase | BindingFlags.NonPublic;

I>            typeof(Program).InvokeMember("Parse" + s, bindingFlags, null, null, null);
I>        }
I>

Фи, рефлексию ради такого дела применять.
Я бы словарь с делегатами забабахал.
Re: switch убрать.
От: 0x7be СССР  
Дата: 11.06.13 11:17
Оценка: 1 (1)
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, у меня очень простой вопрос(мне думается). Создал класс, а нем метод(см. ниже). Каким образом можно избавиться от switch. Вроде бы так делать не желательно, это же ООП язык и нужно применять, что то более грамотное(полиморфизм и все что с этим связано). Если количество выборок увеличится, то switch станет ну очень неприятным. Есть ли общепринятые методики для таких вот фрагментов?

Чтобы ответить на твой вопрос, надо понять, чего ты хочешь в будущем от этого кода.
Re[3]: switch убрать.
От: Mihas  
Дата: 11.06.13 11:18
Оценка:
Здравствуйте, Ilinichev, Вы писали:

I>
AS>>private Dictionary<string, Action> _d = new Dictionary<string, Action>
AS>>{
AS>>         { "txt", ParseTXT },
AS>>......
AS>>}
I>


I>Насколько оправдано здесь применение такой тяжелой структуры данных как Dictionary?


В чем тяжесть?

ИМХО
С одной стороны, инициализация Dictionary выглядит компактнее, чем switch с тем же количеством ветвлений.
С другой стороны, switch гибче, если вдруг сигнатура ParseTXT резко станет отличаться от какого-нибудь ParsePDF.
Re: switch убрать.
От: AK85 Беларусь  
Дата: 11.06.13 11:31
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>Вроде бы так делать не желательно, это же ООП язык и нужно применять, что то более грамотное(полиморфизм и все что с этим связано).

Полнейший бред.
Switch это элегантная, лекго читаемая и изменяемая конструкция.
Re: switch убрать.
От: Sinatr Германия  
Дата: 11.06.13 11:37
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Каким образом можно избавиться от switch. Есть ли общепринятые методики для таких вот фрагментов?


Есть паттерны ага.

У меня один проект на свитчах, намучался, второй уже писал используя делегаты и функции в виде связанного списка (каждая функция это один из шагов свитча, они выполняются и передают управление дальше, по "траектории", которая определяет поток выполнения).

Первое что можно сделать — это ввести enum для типов:

enum FileType {Txt, Conf, Log, Unknown};


Далее можно пойти по пути TypeConverter — вызывать все обработчики, а уже пусть обработчики решают "могут" они или не могут. Типа:



interface IParse
{
    bool CanParse(FileType file);
    void Parse(...);
}

class ParseLog : IParse
{
    bool CanParse(FileType file) {return file == FileType.Log;}
    void Parse(...) {...}
}

class ParseTxt : IParse
{
    bool CanParse(FileType file) {return file == FileType.Txt;}
    void Parse(...) {...}
}

...

ParseLog _log = new ParseLog();
ParseTxt _txt = new ParseLog();
...

IParse[] _parsers = new IParse[] {_log, _txt, ...};

public bool Parse(FileType file, ...)
{
    foreach(var parser in _parsers)
        if(parser.CanParse(file))
            parser.Parse(...);
}


Возможно есть более кавайное решение для группировки парсеров. В данном случае при добавление нового парсера его нужно происнтансцинировать и добавить в список _list, дальше все работает автоматически.. Оо .. (почти ООП)
---
ПроГLамеры объединяйтесь..
Re[2]: switch убрать.
От: Sinatr Германия  
Дата: 11.06.13 11:39
Оценка:
S>
S>ParseTxt _txt = new ParseTxt();
S>
---
ПроГLамеры объединяйтесь..
Re[2]: switch убрать.
От: hardcase Пират http://nemerle.org
Дата: 11.06.13 11:51
Оценка:
Здравствуйте, Sinatr, Вы писали:

S>Далее можно пойти по пути TypeConverter — вызывать все обработчики, а уже пусть обработчики решают "могут" они или не могут. Типа:


Что делать в случае, когда два парсера заявят о том, что они могут разобрать входные данные?
/* иЗвиНите зА неРовнЫй поЧерК */
Re[2]: switch убрать.
От: Аноним  
Дата: 11.06.13 11:57
Оценка:
Кстати, а можно ли в Dictionary добавить, не вызов функции, а непосредственно код, что то в стиле анонимных функций как в perl?
Re[3]: switch убрать.
От: Sinatr Германия  
Дата: 11.06.13 11:59
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Что делать в случае, когда два парсера заявят о том, что они могут разобрать входные данные?


Возможно именно это как раз и было нужно, раз уж написали 2 парсера? Ведь неизвестно чем является результат работы парсеров. Конфликт по идее можно разрешить просто: первый кто может разобрать (или последний) — разбирает.

А вообще да, еще одно необходимое условие для добавки нового парсера — это добавить в enum понимаемый им FileType. Как-то неподумалось.
---
ПроГLамеры объединяйтесь..
Re[3]: switch убрать.
От: Sinatr Германия  
Дата: 11.06.13 12:04
Оценка:
Здравствуйте, Аноним, Вы писали:

А>можно ли в Dictionary добавить, не вызов функции, а непосредственно код?


Неплохая идея. И кстате да, можно, здесь вот как-бы работает.
---
ПроГLамеры объединяйтесь..
Re: anti-dictionary
От: Ilinichev  
Дата: 11.06.13 12:27
Оценка:
А меня Dictionary всегда смущает. Ведь назначение Dictionary — поиск в больших массивах данных, ну при нескольких сотнях вхождений хотя бы. А тут простая таблица соответствия нужна.
В Reflection тоже не вижу ничего плохого, в более-менее нормальных (особенно UI) приложениях он используется повсеместно, если даже неявно, тем более динамическую привязку можно оптимизировать. Я бы не стал называть использование Reflection обременением за исключением специфичных областей по перелопачиванию огромных массивов информации на скорость.
Соглашение об именовании — это вообще один из столпов программирования.

А для своего личного использования пример с Dictionary (без Reflection) я бы переписал примерно так (для меня гораздо читабельнее, и было бы гораздо легче понять впоследствии, что тут и для чего):

using System;
using System.Linq;
using System.Reflection;

namespace ConsoleApplication1
{
    static class Program
    {
        static ParserEntry[] _parsers = new ParserEntry[] {
            "txt".ParseWith(ParseTxt),
            "conf".ParseWith(ParseConf)
        };

        static ParserEntry ParseWith(this string inFile, Action action)
        {
            return new ParserEntry() { InFile = inFile, Action = action };
        }

        struct ParserEntry
        {
            public string InFile;
            public Action Action;
        }   
        
        static void Main(string[] args)
        {
            var str = new string[] { "txt", "conf", "TXT" };

            foreach (var s in str)
            {
                _parsers.Single(p => string.Compare(s, p.InFile, true) == 0).Action();
            }
        }

        static void ParseTxt()
        {
            Console.WriteLine("ParseTxt");
        }

        static void ParseConf()
        {
            Console.WriteLine("ParseConf");
        }
    }
}
Re[2]: anti-dictionary
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 11.06.13 12:33
Оценка: 2 (1) +1
Здравствуйте, Ilinichev, Вы писали:

I>А меня Dictionary всегда смущает. Ведь назначение Dictionary — поиск в больших массивах данных


Назначение Dictionary — ассоциативный массив.

I>, ну при нескольких сотнях вхождений хотя бы.


Посмотри как компилятор C# компилирует строковый свитч хотя бы вариантов на 10 — сильно удивишься.

I>В Reflection тоже не вижу ничего плохого


А зря.

I>в более-менее нормальных (особенно UI) приложениях он используется повсеместно


Использоваться он, конечно, используется, то там где можно без него, нужно без него.
... << RSDN@Home 1.2.0 alpha 5 rev. 99 on Windows 8 6.2.9200.0>>
AVK Blog
Re[3]: anti-dictionary
От: Ilinichev  
Дата: 11.06.13 12:49
Оценка: 1 (1)
Здравствуйте, AndrewVK, Вы писали:

I>>А меня Dictionary всегда смущает. Ведь назначение Dictionary — поиск в больших массивах данных

AVK>Назначение Dictionary — ассоциативный массив.

Посредством вычисления хеш-значения. Какова целесообразность этого для десяти постоянных значений?

AVK>Посмотри как компилятор C# компилирует строковый свитч хотя бы вариантов на 10 — сильно удивишься.


Dictionary Но это ведь не значит, что оптимизатор прав, создавая хэш для десяти значений, когда можно обойтись двухстолбцовой таблицей.

I>>в более-менее нормальных (особенно UI) приложениях он используется повсеместно

AVK>Использоваться он, конечно, используется, то там где можно без него, нужно без него.

У ТС, могу предположить, как раз тот случай. Вполне вероятно парсеры у него подключаются как плагины через конфигурационный файл
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.