Здравствуйте, Ilinichev, Вы писали:
I>Посредством вычисления хеш-значения. Какова целесообразность этого для десяти постоянных значений?
Вполне себе.
AVK>>Посмотри как компилятор C# компилирует строковый свитч хотя бы вариантов на 10 — сильно удивишься. I>Dictionary Но это ведь не значит, что оптимизатор прав
Ну конечно, тебе виднее
I>, создавая хэш для десяти значений, когда можно обойтись двухстолбцовой таблицей.
Что такое "двухстолбцовая таблица"?
AVK>>Использоваться он, конечно, используется, то там где можно без него, нужно без него. I>У ТС, могу предположить, как раз тот случай.
Это почему это? Его задача хорошо решается и без рефлекшена.
I> Вполне вероятно парсеры у него подключаются как плагины через конфигурационный файл
Да да, а потом варианты хардкодятся в switch
... << RSDN@Home 1.2.0 alpha 5 rev. 99 on Windows 8 6.2.9200.0>>
Здравствуйте, Аноним, Вы писали:
А> Есть ли общепринятые методики для таких вот фрагментов?
Ну вот так например:
class Program
{
static void Main(string[] args)
{
var magicChecker = new MagicCheckerBuilder()
.WithParser("txt", new TxtParser())
.WithParser("conf", new ConfParser())
.WithParser("log", new LogParser())
.Build();
var yourService = new YourService(magicChecker);
yourService.CheckFiles("conf");
}
}
public class YourService
{
private readonly MagicChecker _magicChecker;
public YourService(MagicChecker magicChecker)
{
_magicChecker = magicChecker;
}
public void CheckFiles(string inFile)
{
_magicChecker.MagicallyCheck(inFile);
}
}
public class MagicChecker
{
private readonly IDictionary<string, IParser> _parsers;
public MagicChecker(IDictionary<string, IParser> parsers)
{
_parsers = parsers;
}
public void MagicallyCheck(string inFile)
{
var haveNoIdeaWhatToDo = !_parsers.ContainsKey(inFile);
if (haveNoIdeaWhatToDo)
{
throw new Exception("Have no idea what to do");
}
var parser = _parsers[inFile];
parser.Parse();
}
}
public class MagicCheckerBuilder
{
private readonly IDictionary<string, IParser> _parsers = new Dictionary<string, IParser>();
public MagicCheckerBuilder WithParser(string inFile, IParser parser)
{
_parsers.Add(inFile, parser);
return this;
}
public MagicChecker Build()
{
return new MagicChecker(_parser);
}
}
public interface IParser
{
void Parse();
}
public class TxtParser : IParser
{
public void Parse()
{
throw new NotImplementedException();
}
}
public class ConfParser : IParser
{
public void Parse()
{
throw new NotImplementedException();
}
}
public class LogParser : IParser
{
public void Parse()
{
throw new NotImplementedException();
}
}
I>>>А меня Dictionary всегда смущает. Ведь назначение Dictionary — поиск в больших массивах данных AVK>>Назначение Dictionary — ассоциативный массив. I>Посредством вычисления хеш-значения. Какова целесообразность этого для десяти постоянных значений?
Отвечайте на это сообщение, только если у Вас хорошее настроение и в Вашем ответе планируются только конструктивные вопросы и замечания http://rsdn.ru/Info/rules.xml
AVK>Написать на коленке типизированные недолго, благо ListDictionary примитивен донельзя. Вот только будет ли выигрыш заметный — большой вопрос.
Зависит от того сколько раз будет вызывать код с ListDictionary, если один раз в день, то выигрыша не будет.
Если 1000 раз в сек, то выигрыш будет.
Отвечайте на это сообщение, только если у Вас хорошее настроение и в Вашем ответе планируются только конструктивные вопросы и замечания http://rsdn.ru/Info/rules.xml
Здравствуйте, igor-booch, Вы писали:
AVK>>Написать на коленке типизированные недолго, благо ListDictionary примитивен донельзя. Вот только будет ли выигрыш заметный — большой вопрос. IB>Зависит от того сколько раз будет вызывать код с ListDictionary, если один раз в день, то выигрыша не будет. IB>Если 1000 раз в сек, то выигрыш будет.
Учитывая что у ТС — там парсинг лога / кофиг, файловый IO — этой разницы не будет видно даже в электронный микроскоп.
Здравствуйте, fddima, Вы писали:
AVK>>>Написать на коленке типизированные недолго, благо ListDictionary примитивен донельзя. Вот только будет ли выигрыш заметный — большой вопрос. IB>>Зависит от того сколько раз будет вызывать код с ListDictionary, если один раз в день, то выигрыша не будет. IB>>Если 1000 раз в сек, то выигрыш будет. F> Учитывая что у ТС — там парсинг лога / кофиг, файловый IO — этой разницы не будет видно даже в электронный микроскоп.
Боюсь вас огорчить, но электронный микроскоп не профайлит
Здравствуйте, Ilinichev, Вы писали:
F>> Учитывая что у ТС — там парсинг лога / кофиг, файловый IO — этой разницы не будет видно даже в электронный микроскоп. I>Боюсь вас огорчить, но электронный микроскоп не профайлит
А профайлить и не надо, что бы понять, что методы Parse* будут занимать 99.9% времени.
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, у меня очень простой вопрос(мне думается). Создал класс, а нем метод(см. ниже). Каким образом можно избавиться от switch. Вроде бы так делать не желательно, это же ООП язык и нужно применять, что то более грамотное(полиморфизм и все что с этим связано). Если количество выборок увеличится, то switch станет ну очень неприятным. Есть ли общепринятые методики для таких вот фрагментов?
Если с т.з. именно ООП то по идее так
////////
// ИНТЕРФЕЙС И ФАБРИКА ДЛЯ СОЗДАНИЯ ОБЪЕКТОВ
/////////public interface IParser
{
void Parse();
}
public static class ParserFactory
{
// Эту штуку можно динамически создавать из app.config напримерstatic ReadOnlyDictionary<string,Type> _parsersNameTypeMap
{
{"txt", typeof(TextParser)}
{"cfg", typeof(ConfigParser)}
}
public static IParser CreateFromExtension( string extension )
{
if (!_parsersNameTypeMap.ContainsKey(extension))
throw new ArgumentException("Неизвестное расширение '" + extension + "'" );
var parser = Activator.CreateInstance( _parserNameTypeMap[ extension ] ) as IParser;
if ( parser == null )
throw new ArgumentException("Для расширения '" + extension + "' задан тип не совместимый с интерфейсом IParser");
return parser;
}
}
/////////////////
// Описание различных алгоритмов парсинга
/////////////////public class TextParser : IParser
{
void Parse()
{
//....
}
}
public class ConfigParser : IParser
{
void Parse()
{
}
}
Здравствуйте, igor-booch, Вы писали:
IB>Зависит от того сколько раз будет вызывать код с ListDictionary, если один раз в день, то выигрыша не будет. IB>Если 1000 раз в сек, то выигрыш будет.
Дабы закончить свою мысль. Всё дело в если. В ListDictionary и их аналогах есть свои нюансы как и в обычном Dictionary. У Dictionary будет несколько большая косвенность, зато оно даст константное среднее время доступа, а ListDictionary — никогда. Если "1000 раз в сек" спрашивать 10-ый элемент? Но это ерунда.
А, если у нас 3-5 варианта выбора. А, если мы накладываем ограничение, что поданная строка должна быть пропущена через таблицу символов (а-ля интернирована), то банальный if-else с простым сравнением ссылок порвёт любой вариант Dictionary.
Ещё не много если? А если у нас парсер парсит лог секунду (или скажем поближе к реальности — минуты две), толку то.
Микробенчмарки не только нынче не в моде, а ещё и полностью бесполезны, т.к. доступ к памяти — вещь очень неконстантная и зависит собственно от загрузки хоста. Все остальные критерии ничего не значит, код должен быть понятен и прост насколько это возможно (при прочих равных показателях).
Лучше вот тут бы предложил http://www.rsdn.ru/forum/dotnet/5196714.1
Отвечайте на это сообщение, только если у Вас хорошее настроение и в Вашем ответе планируются только конструктивные вопросы и замечания http://rsdn.ru/Info/rules.xml
Здравствуйте, igor-booch, Вы писали:
S>>У меня один проект на свитчах, намучался IB>А в чем заключались мучения?
Сначала все было хорошо, потом появились case внутри которых был довольно увесистый блок кода (а выносить в отдельную функцию было накладно, т.к. много локальных переменных использовалось в самом коде), потом появилась необходимость заводить локальные и глобальные переменные для определенных case-ов, потом появилась необходимость выполнить несколько свитчей за раз и вернутся (что-то вроде вызова подпрограммы, выполняющей шаг, который используется в нескольких местах) и тд.
Новый проект писал с делегатами.. стало как-то красиво и легко вдруг (именно сапортить легко). Словами не обьяснить, понимание приходит когда количество case-ов за 50.
Здравствуйте, Sinatr, Вы писали:
S>Сначала все было хорошо, потом появились case внутри которых был довольно увесистый блок кода (а выносить в отдельную функцию было накладно, т.к. много локальных переменных использовалось в самом коде), потом появилась необходимость заводить локальные и глобальные переменные для определенных case-ов, потом появилась необходимость выполнить несколько свитчей за раз и вернутся (что-то вроде вызова подпрограммы, выполняющей шаг, который используется в нескольких местах) и тд.
И как так выходит, что выносить в отдельную функцию — накладно, а с делегатом(по сути — такой же функцией только вид сбоку) — красиво и легко?
Здравствуйте, Yoriсk, Вы писали:
Y>И как так выходит, что выносить в отдельную функцию — накладно, а с делегатом(по сути — такой же функцией только вид сбоку) — красиво и легко?
Это уже придирки. Но если смотреть на switch/case в любом виде (будь там код или вызовы отдельных функций), то это больше похоже на кашу, в которой сложно разобраться (когда необходимо внести изменения через год или вообще другому человеку). С функциями и делегатами выглядит более элегантно что ли.
Понятно, что switch/case нужны и полезны, но в определенных случаях ими пользоваться неудобно. Взять пример ТС и 50 парсеров — получится каша. Если много чего-то "похожего", то программист всегда предпочтет организовать это в цикле. Исключение — если нужна оптимизация по скорости или индусский код.