Здравствуйте, у меня очень простой вопрос(мне думается). Создал класс, а нем метод(см. ниже). Каким образом можно избавиться от switch. Вроде бы так делать не желательно, это же ООП язык и нужно применять, что то более грамотное(полиморфизм и все что с этим связано). Если количество выборок увеличится, то switch станет ну очень неприятным. Есть ли общепринятые методики для таких вот фрагментов?
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, у меня очень простой вопрос(мне думается). Создал класс, а нем метод(см. ниже). Каким образом можно избавиться от 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// не нашли
А> }
А>
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, у меня очень простой вопрос(мне думается). Создал класс, а нем метод(см. ниже). Каким образом можно избавиться от 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");
}
}
}
Здравствуйте, <Аноним>, Вы писали:
А>Здравствуйте, у меня очень простой вопрос(мне думается). Создал класс, а нем метод(см. ниже). Каким образом можно избавиться от switch.
А зачем?
А> Вроде бы так делать не желательно, это же ООП язык и нужно применять, что то более грамотное(полиморфизм и все что с этим связано). Если количество выборок увеличится, то switch станет ну очень неприятным.
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, у меня очень простой вопрос(мне думается). Создал класс, а нем метод(см. ниже). Каким образом можно избавиться от switch. Вроде бы так делать не желательно, это же ООП язык и нужно применять, что то более грамотное(полиморфизм и все что с этим связано). Если количество выборок увеличится, то switch станет ну очень неприятным. Есть ли общепринятые методики для таких вот фрагментов?
Чтобы ответить на твой вопрос, надо понять, чего ты хочешь в будущем от этого кода.
I>Насколько оправдано здесь применение такой тяжелой структуры данных как Dictionary?
В чем тяжесть?
ИМХО
С одной стороны, инициализация Dictionary выглядит компактнее, чем switch с тем же количеством ветвлений.
С другой стороны, switch гибче, если вдруг сигнатура ParseTXT резко станет отличаться от какого-нибудь ParsePDF.
Здравствуйте, Аноним, Вы писали:
А>Вроде бы так делать не желательно, это же ООП язык и нужно применять, что то более грамотное(полиморфизм и все что с этим связано).
Полнейший бред.
Switch это элегантная, лекго читаемая и изменяемая конструкция.
Здравствуйте, Аноним, Вы писали:
А>Каким образом можно избавиться от switch. Есть ли общепринятые методики для таких вот фрагментов?
Есть паттерны ага.
У меня один проект на свитчах, намучался, второй уже писал используя делегаты и функции в виде связанного списка (каждая функция это один из шагов свитча, они выполняются и передают управление дальше, по "траектории", которая определяет поток выполнения).
Первое что можно сделать — это ввести enum для типов:
enum FileType {Txt, Conf, Log, Unknown};
Далее можно пойти по пути TypeConverter — вызывать все обработчики, а уже пусть обработчики решают "могут" они или не могут. Типа:
Возможно есть более кавайное решение для группировки парсеров. В данном случае при добавление нового парсера его нужно происнтансцинировать и добавить в список _list, дальше все работает автоматически.. Оо .. (почти ООП)
Здравствуйте, Sinatr, Вы писали:
S>Далее можно пойти по пути TypeConverter — вызывать все обработчики, а уже пусть обработчики решают "могут" они или не могут. Типа:
Что делать в случае, когда два парсера заявят о том, что они могут разобрать входные данные?
/* иЗвиНите зА неРовнЫй поЧерК */
Re[2]: switch убрать.
От:
Аноним
Дата:
11.06.13 11:57
Оценка:
Кстати, а можно ли в Dictionary добавить, не вызов функции, а непосредственно код, что то в стиле анонимных функций как в perl?
Здравствуйте, hardcase, Вы писали:
H>Что делать в случае, когда два парсера заявят о том, что они могут разобрать входные данные?
Возможно именно это как раз и было нужно, раз уж написали 2 парсера? Ведь неизвестно чем является результат работы парсеров. Конфликт по идее можно разрешить просто: первый кто может разобрать (или последний) — разбирает.
А вообще да, еще одно необходимое условие для добавки нового парсера — это добавить в enum понимаемый им FileType. Как-то неподумалось.
А меня 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");
}
}
}
Здравствуйте, AndrewVK, Вы писали:
I>>А меня Dictionary всегда смущает. Ведь назначение Dictionary — поиск в больших массивах данных AVK>Назначение Dictionary — ассоциативный массив.
Посредством вычисления хеш-значения. Какова целесообразность этого для десяти постоянных значений?
AVK>Посмотри как компилятор C# компилирует строковый свитч хотя бы вариантов на 10 — сильно удивишься.
Dictionary Но это ведь не значит, что оптимизатор прав, создавая хэш для десяти значений, когда можно обойтись двухстолбцовой таблицей.
I>>в более-менее нормальных (особенно UI) приложениях он используется повсеместно AVK>Использоваться он, конечно, используется, то там где можно без него, нужно без него.
У ТС, могу предположить, как раз тот случай. Вполне вероятно парсеры у него подключаются как плагины через конфигурационный файл