Я нахожусь в заключительных этапах создания синтаксического анализатора тега MP4 в .NET. Для тех, у кого есть опыт с метками музыки, Вы знали бы, что существует в среднем приблизительно 30 тегов. Если проверил различные типы циклов, и кажется, что оператор переключения со значениями Константы, кажется, способ пойти относительно ловли тегов в двоичном файле.
Переключатель позволяет мне искать двоичный файл без потребности знать, какой порядок теги хранятся или если бы существуют, некоторые не представляют, но интересно, был ли кто-либо против использования оператора переключения для такого количества условных выражений.
Любое понимание очень ценится.
Править: Каждый думает, что я должен добавить теперь, когда, где обсуждение этого состоит в том, что функция является рекурсивной, я должен вытащить это условное выражение и передать данные методу, который я могу уничтожить?
Лично, если нужно, я бы пошел этим путем. Оператор switch намного легче читать, чем операторы If / Else (и в вашем размере будет оптимизирован для вас).
Вот связанный с этим вопрос. Обратите внимание, что принятый ответ неверен.
Есть ли существенная разница между использованием if / else и switch-case в C #?
Возможно, с переключателем все будет нормально, но я думаю, ваша функция станет очень долгой.
Один из способов решить эту проблему - создать класс обработчика для каждого типа тега и затем зарегистрировать каждый обработчик с соответствующим тегом в словаре. Когда вам нужно разобрать тег, вы можете посмотреть в словаре, какой обработчик следует использовать.
Для чего-то такого низкого уровня я не вижу проблемы. Просто убедитесь, что вы поместили каждый случай в отдельный метод. Вы поблагодарите себя позже.
Я хотел добавить свой собственный ответ, чтобы оттолкнуть людей ...
Трудно сказать, не видя своего кода, но если вы просто пытаетесь поймать каждый тег, вы можете определить массив допустимых тегов, а затем просмотреть файл в цикле, проверяя, есть ли каждый тег в массиве.
Другой вариант (вдохновленный Python) - словарь, который сопоставляет тег с лямбда-функцией, или событием, или чем-то подобным. Это потребует некоторой перестройки архитектуры.
Для меня, имея так много условий в операторе switch дает мне повод для размышлений. Возможно, было бы лучше реорганизовать код и полагаться на виртуальные методы, связь между тегами и методами или любой другой механизм, чтобы избежать спагетти-кода.
ID3Sharp на Sourceforge имеет http://sourceforge.net/projects/id3sharp/ использует более объектно-ориентированный подход с FrameRegistry, который раздает производные классы для каждого типа фреймов.
Это быстро, это хорошо работает, и это легко поддерживать. Накладные расходы на создание небольшого объекта класса в C# ничтожно малы по сравнению с открытием файла MP4 для чтения заголовка.
Один дизайн, который может быть полезен в некоторых случаях (но, судя по тому, что я видел, здесь было бы слишком убивать):
class DoStuff
{
public void Do(type it, Context context )
{
switch(it)
{
case case1: doCase1(context) break;
case case2: doCase2(context) break;
//...
}
}
protected abstract void doCase1(Context context);
protected abstract void doCase2(Context context);
//...
}
class DoRealStuff : DoStuff
{
override void doCase1(Context context) { ... }
override void doCase2(Context context) { ... }
//...
}
Если у вас есть только одно место с такой конкретной структурой операторов switch
и case
, то это вопрос стиля. Если у вас есть несколько мест с одинаковой структурой, вы можете переосмыслить, как вы это делаете, чтобы свести к минимуму головную боль при обслуживании.
Что о старый добрый цикл? Я думаю, вы можете так спроектировать. Разве switch-case в любом случае не преобразуется только в if-else? Я всегда стараюсь писать код с использованием цикла, если количество операторов case становится выше допустимого. А 30 случаев в свитче для меня слишком много.
Я не знаком с технологией MP4, но хотел бы изучить возможность использования здесь некоторых интерфейсов. Передайте объект, попробуйте передать его в интерфейс.
public void SomeMethod(object obj)
{
ITag it = obj as ITag;
if(it != null)
{
it.SomeProperty = "SomeValue";
it.DoSomthingWithTag();
}
}
У вас почти наверняка есть цепочка ответственности в вашей проблеме. Рефакторинг.