c# - operaciones - ¿Está bien una declaración de cambio para 30 o más condiciones?
instructivo formulario 4 (13)
Estoy en las etapas finales de crear un analizador de etiquetas MP4 en .Net. Para aquellos que tienen experiencia en etiquetar música, deberían saber que hay un promedio de 30 etiquetas aproximadamente. Si se prueban diferentes tipos de bucles y parece que una instrucción de cambio con valores Const parece ser el camino a seguir para capturar las etiquetas en binario.
El conmutador me permite buscar el binario sin la necesidad de saber qué orden están almacenadas las etiquetas o si hay algunas que no están presentes, pero me pregunto si alguien estaría en contra de usar una declaración de conmutación para tantos condicionales.
Cualquier idea es muy apreciada.
EDITAR: Creo que debo agregar ahora que cuando se discute esto es que la función es recursiva, ¿debo sacar este condicional y pasar los datos a un método que pueda eliminar?
¿Qué hay de Good Old for Loop? Creo que puedes diseñarlo de esa manera. ¿El cambio de mayúsculas y minúsculas no se transforma si no? Siempre trato de escribir código usando bucle si la cantidad de declaraciones de casos es más alta que la aceptable. Y 30 casos en el interruptor es demasiado alto para mí.
Es casi seguro que tienes una Cadena de Responsabilidad en tu problema. Refactor
Es difícil decirlo sin ver su código, pero si solo está intentando capturar cada etiqueta, puede definir una matriz de etiquetas aceptables, luego hacer un bucle a través del archivo, verificando si cada etiqueta está en la matriz.
ID3Sharp en Sourceforge tiene un http://sourceforge.net/projects/id3sharp/ utiliza un enfoque más orientado a objetos con un FrameRegistry que reparte las clases derivadas para cada tipo de marco.
Es rápido, funciona bien y es fácil de mantener. La "sobrecarga" de crear un objeto de clase pequeña en C # es insignificante en comparación con abrir un archivo MP4 para leer el encabezado.
No estoy familiarizado con la tecnología MP4 pero exploraría la posibilidad de usar algunas interfaces aquí. Pasar en un objeto, tratar de lanzar a la interfaz.
public void SomeMethod(object obj)
{
ITag it = obj as ITag;
if(it != null)
{
it.SomeProperty = "SomeValue";
it.DoSomthingWithTag();
}
}
Otra opción (inspirada en Python) es un diccionario que asigna una etiqueta a una función lambda, o un evento, o algo así. Requeriría alguna re-arquitectura.
Para algo bajo nivel como este no veo un problema. Solo asegúrate de colocar cada caso en un método separado. Te lo agradecerás más tarde.
Para mí, tener tantas condiciones en una declaración de cambio me da razones para pensar. Podría ser mejor refactorizar el código y confiar en métodos virtuales, asociación entre etiquetas y métodos, o cualquier otro mecanismo para evitar el código spagetti.
Personalmente, si es necesario, me gustaría ir por este camino. Una declaración de cambio es mucho más fácil de leer que las declaraciones If / Else (y en su tamaño se optimizarán para usted).
Aquí hay una pregunta relacionada. Tenga en cuenta que la respuesta aceptada es la incorrecta.
¿Hay alguna diferencia significativa entre usar if / else y switch-case en C #?
Probablemente funcionará bien con el interruptor, pero creo que su función será muy larga.
Una forma de resolver esto es crear una clase de manejador para cada tipo de etiqueta y luego registrar cada manejador con la etiqueta correspondiente en un diccionario. Cuando necesite analizar una etiqueta, puede buscar en el diccionario el controlador que se debe usar.
Quería agregar mi propia respuesta solo para despedir a la gente ...
- Cree un objeto que contenga el "nombre de etiqueta binario", "Datos", "Nombre de propiedad".
- Cree una lista de estos que sumen la cantidad de etiquetas conocidas agregando el nombre de la etiqueta y el nombre de la propiedad.
- Al analizar, use linq para hacer coincidir el nombre encontrado con el object.binarytagname y agregar los datos
- reflexionar en la propiedad y añadir los datos ...
Si solo tiene un lugar que tiene esa estructura particular de declaraciones de switch
y case
, entonces es una cuestión de estilo. Si tiene más de un lugar que tiene la misma estructura, es posible que desee volver a pensar cómo lo hace para minimizar los dolores de cabeza de mantenimiento.
Un diseño que podría ser útil en algún caso (pero por lo que he visto sería una matanza excesiva aquí):
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) { ... }
//...
}