Capítulo 6: La sentencia switch en C#

6 min de lectura

Parte I - Sección 2: Lógica de programación - Nivel: Principiante


Objetivos de aprendizaje

Al finalizar este capítulo serás capaz de:

  • Usar la estructura switch para comparar una variable contra múltiples valores
  • Entender cuándo switch es mejor que múltiples else if
  • Manejar casos múltiples con fall-through controlado
  • Usar el caso default para valores no esperados
  • Construir configuradores de componentes con muchas opciones

Requisitos previos

Antes de comenzar este capítulo debes:

  • Haber completado el Capítulo 5
  • Entender estructuras if/else if
  • Saber comparar valores con ==
  • Conocer tipos de datos básicos

Proyecto del capítulo

Configurador de Componentes Eléctricos

Al final de este capítulo habrás construido un script que:

  • Identifica componentes por su código de artículo
  • Obtiene especificaciones técnicas completas
  • Genera descripciones formateadas para documentación
  • Maneja decenas de opciones de forma organizada

Contenido

1. Introducción: El problema con muchos else if

En el capítulo anterior vimos este código:

if (tipoCarga == "Motor")
{
    curva = "D";
}
else if (tipoCarga == "Iluminacion")
{
    curva = "B";
}
else if (tipoCarga == "Tomas")
{
    curva = "C";
}
else if (tipoCarga == "Informatica")
{
    curva = "C";
}
else
{
    curva = "C";
}

Esto funciona, pero con muchas opciones se vuelve repetitivo y difícil de leer.

Problema real: Imagina un configurador que debe identificar 50 tipos diferentes de interruptores por su código de artículo. Con else if tendrías 50 bloques casi idénticos.

Solución: La estructura switch.


2. La estructura switch básica

Sintaxis:

switch (variable)
{
    case valor1:
        // Código si variable == valor1
        break;
    case valor2:
        // Código si variable == valor2
        break;
    default:
        // Código si ningún case coincide
        break;
}

Ejemplo práctico - mismo caso anterior:

string tipoCarga = "Motor";
string curva;

switch (tipoCarga)
{
    case "Motor":
        curva = "D";
        break;
    case "Iluminacion":
        curva = "B";
        break;
    case "Tomas":
        curva = "C";
        break;
    case "Informatica":
        curva = "C";
        break;
    default:
        curva = "C";
        break;
}

Ventajas:

  • Más legible cuando hay muchas opciones
  • Intención clara: "evaluar variable contra valores"
  • Fácil de mantener y extender

3. Anatomía del switch

switch (expresion)  ← Variable o expresión a evaluar
{
    case valorConstante1:  ← Valor específico a comparar
        // Código
        break;  ← OBLIGATORIO: sale del switch

    case valorConstante2:
        // Código
        break;

    default:  ← Opcional: caso "ninguno de los anteriores"
        // Código
        break;
}

3.1 Reglas importantes

1. La expresión puede ser: int, string, char, enum, bool (no double ni float)

// Válido
switch (corrienteNominal)  // int
switch (tipoCarga)         // string
switch (estado)            // char
switch (tipoProteccion)    // enum

// NO válido
switch (voltaje)           // double - ERROR
switch (temperatura)       // float - ERROR

2. Cada case debe terminar con break

switch (tipo)
{
    case "A":
        MessageBox.Show("Tipo A");
        break;  // OBLIGATORIO
    case "B":
        MessageBox.Show("Tipo B");
        // Sin break → ERROR de compilación
}

3. Los valores de case deben ser constantes

const string TIPO_MOTOR = "Motor";
int limite = 16;

switch (tipoCarga)
{
    case TIPO_MOTOR:        // OK: constante
        break;
    case "Iluminacion":     // OK: literal
        break;
    case limite:            // ERROR: no es constante
        break;
}

4. Ejemplos prácticos básicos

4.1 Switch con int - Seleccionar sección de cable

int corrienteNominal = 20;
double seccionCable;

switch (corrienteNominal)
{
    case 10:
        seccionCable = 1.5;
        break;
    case 16:
        seccionCable = 2.5;
        break;
    case 20:
        seccionCable = 4.0;
        break;
    case 25:
        seccionCable = 6.0;
        break;
    case 32:
        seccionCable = 10.0;
        break;
    default:
        seccionCable = 16.0;
        break;
}

MessageBox.Show(string.Format("Corriente: {0}A → Sección: {1}mm²",
    corrienteNominal, seccionCable));

4.2 Switch con string - Tipo de instalación

string ambiente = "Humedo";
string tipoInstalacion;

switch (ambiente)
{
    case "Seco":
        tipoInstalacion = "Instalación estándar (B1)";
        break;
    case "Humedo":
        tipoInstalacion = "Instalación protegida contra agua (B2)";
        break;
    case "Mojado":
        tipoInstalacion = "Instalación sumergible (B3)";
        break;
    case "Corrosivo":
        tipoInstalacion = "Instalación con protección química (B4)";
        break;
    default:
        tipoInstalacion = "No especificado - revisar manualmente";
        break;
}

MessageBox.Show(tipoInstalacion);

4.3 Switch con char - Clase de aislamiento

char claseAislamiento = 'F';
int temperaturaMaxima;

switch (claseAislamiento)
{
    case 'Y':
        temperaturaMaxima = 90;
        break;
    case 'A':
        temperaturaMaxima = 105;
        break;
    case 'E':
        temperaturaMaxima = 120;
        break;
    case 'B':
        temperaturaMaxima = 130;
        break;
    case 'F':
        temperaturaMaxima = 155;
        break;
    case 'H':
        temperaturaMaxima = 180;
        break;
    default:
        temperaturaMaxima = 0;
        break;
}

MessageBox.Show(string.Format("Clase {0}: Temperatura máxima {1}°C",
    claseAislamiento, temperaturaMaxima));

5. Casos múltiples (multiple cases)

Cuando varios valores deben ejecutar el mismo código:

switch (variable)
{
    case valor1:
    case valor2:
    case valor3:
        // Código para valor1, valor2 o valor3
        break;
    case valor4:
        // Código solo para valor4
        break;
}

5.1 Ejemplo: Clasificar grado de protección IP

int gradoProteccionIP = 54;  // IP54

string descripcion;

switch (gradoProteccionIP)
{
    case 20:
    case 21:
    case 22:
        descripcion = "Protección básica interior";
        break;
    case 44:
    case 54:
    case 55:
        descripcion = "Protección contra polvo y agua (uso industrial)";
        break;
    case 65:
    case 66:
    case 67:
        descripcion = "Protección alta contra agua (uso exterior)";
        break;
    case 68:
        descripcion = "Protección total (sumergible)";
        break;
    default:
        descripcion = "Grado IP no reconocido";
        break;
}

MessageBox.Show(string.Format("IP{0}: {1}", gradoProteccionIP, descripcion));

5.2 Ejemplo: Días laborables vs fin de semana

int diaSemana = 3;  // 1=Lunes, 7=Domingo
string tipoTarifa;

switch (diaSemana)
{
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
        tipoTarifa = "Tarifa laboral (mayor consumo industrial)";
        break;
    case 6:
    case 7:
        tipoTarifa = "Tarifa fin de semana (menor consumo)";
        break;
    default:
        tipoTarifa = "Día no válido";
        break;
}

MessageBox.Show(tipoTarifa);

6. El caso default

El bloque default se ejecuta cuando ningún case coincide. Es opcional pero muy recomendable.

6.1 Sin default (peligroso)

string tipo = "X";  // Valor inesperado
string descripcion;

switch (tipo)
{
    case "A":
        descripcion = "Tipo A";
        break;
    case "B":
        descripcion = "Tipo B";
        break;
    // Sin default
}

MessageBox.Show(descripcion);  // ERROR: 'descripcion' no está asignada

6.2 Con default (seguro)

string tipo = "X";
string descripcion;

switch (tipo)
{
    case "A":
        descripcion = "Tipo A";
        break;
    case "B":
        descripcion = "Tipo B";
        break;
    default:
        descripcion = "Tipo desconocido";
        break;
}

MessageBox.Show(descripcion);  // "Tipo desconocido"

6.3 Default para validación

int corriente = 35;  // Valor no estándar
double seccion;

switch (corriente)
{
    case 10:
        seccion = 1.5;
        break;
    case 16:
        seccion = 2.5;
        break;
    case 20:
        seccion = 4.0;
        break;
    case 25:
        seccion = 6.0;
        break;
    default:
        MessageBox.Show("Corriente no estándar. Requiere cálculo manual.");
        return;  // Sale del método
}

MessageBox.Show(string.Format("Sección: {0}mm²", seccion));

7. Switch vs if/else if - ¿Cuándo usar cada uno?

7.1 Usa switch cuando:

Comparas una variable contra valores específicos constantes

// Perfecto para switch
switch (codigoArticulo)
{
    case "3RT2026":
        descripcion = "Contactor 25A";
        break;
    case "3RT2036":
        descripcion = "Contactor 40A";
        break;
    // ... más casos
}

Tienes muchas opciones (>3-4)

Con 10+ opciones, switch es mucho más legible.

Los valores son discretos (no rangos)

// Bien con switch
switch (numeroPolo)
{
    case 1: // ...
    case 2: // ...
    case 3: // ...
    case 4: // ...
}

7.2 Usa if/else if cuando:

Necesitas comparar rangos

// NO puedes hacer esto con switch
if (corriente <= 16.0)
{
    seccion = 2.5;
}
else if (corriente <= 25.0)
{
    seccion = 6.0;
}

Comparas con double o float

// switch NO funciona con double
double voltaje = 230.5;

if (voltaje >= 207.0 && voltaje <= 253.0)
{
    // OK
}

Necesitas condiciones complejas

// Condición compleja - usa if
if (corriente > limite && temperatura < 40 && !alertaActiva)
{
    // ...
}

Comparas diferentes variables en cada condición

// Cada condición evalúa variables diferentes - usa if
if (voltaje > 253)
{
    // ...
}
else if (corriente > 16)
{
    // ...
}
else if (temperatura > 50)
{
    // ...
}

7.3 Tabla comparativa

Criterioswitchif/else if
Tipo de variableint, string, char, enum, boolCualquier tipo
RangosNo
Valores exactosIdealFunciona
Múltiples variablesNo
Condiciones complejasNo
Legibilidad (muchas opciones)MejorSe complica

8. Switch con expresiones (C# 8.0+)

EPLAN 2026 soporta C# moderno, así que puedes usar switch expressions (sintaxis más compacta):

8.1 Sintaxis tradicional vs expression

Tradicional:

string tipoCarga = "Motor";
string curva;

switch (tipoCarga)
{
    case "Motor":
        curva = "D";
        break;
    case "Iluminacion":
        curva = "B";
        break;
    default:
        curva = "C";
        break;
}

Switch expression (más compacto):

string tipoCarga = "Motor";

string curva = tipoCarga switch
{
    "Motor" => "D",
    "Iluminacion" => "B",
    _ => "C"  // _ es el default
};

8.2 Ejemplo práctico con switch expression

int corriente = 20;

double seccion = corriente switch
{
    10 => 1.5,
    16 => 2.5,
    20 => 4.0,
    25 => 6.0,
    32 => 10.0,
    _ => 16.0
};

MessageBox.Show(string.Format("{0}A → {1}mm²", corriente, seccion));

Ventajas:

  • Más conciso
  • Directamente asigna el resultado
  • Menos líneas de código

Cuándo usarlo:

  • Asignaciones simples
  • No necesitas múltiples líneas de código por caso
  • Cuando mejora la legibilidad

Cuándo NO usarlo:

  • Cada caso requiere múltiples líneas
  • Lógica compleja dentro de cada caso
  • Cuando reduce la claridad

Manos a la obra: Construyendo el proyecto

Vamos a crear un Configurador de Componentes Eléctricos que identifica productos por código.

Paso 1: Estructura básica

using System;
using Eplan.EplApi.Base;
using Eplan.EplApi.ApplicationFramework;

public class ConfiguradorComponentes
{
    [Start]
    public void Ejecutar()
    {
        // ========================================
        // CÓDIGO DE ARTÍCULO A CONSULTAR
        // ========================================

        string codigoArticulo = "3RT2026-1BB40";

        // Variables para almacenar información
        string tipoComponente;
        string fabricante;
        string descripcionCorta;
        string descripcionLarga;
        string especificacionesTecnicas;
    }
}

Paso 2: Identificar fabricante por prefijo

// ========================================
// PASO 1: IDENTIFICAR FABRICANTE
// ========================================

string prefijo = codigoArticulo.Substring(0, 3);  // Primeros 3 caracteres

switch (prefijo)
{
    case "3RT":
    case "3RV":
    case "3RA":
    case "3RU":
        fabricante = "Siemens";
        break;
    case "LC1":
    case "LR2":
    case "GV2":
    case "GV3":
        fabricante = "Schneider Electric";
        break;
    case "AF0":
    case "AF1":
    case "AF2":
    case "AX0":
        fabricante = "ABB";
        break;
    case "DIL":
    case "PKZ":
    case "NZM":
        fabricante = "Eaton / Moeller";
        break;
    default:
        fabricante = "Fabricante no identificado";
        break;
}

¿Qué acabamos de hacer? Identificamos el fabricante analizando los primeros 3 caracteres del código de artículo. Diferentes fabricantes usan diferentes prefijos.


Paso 3: Identificar tipo de componente

// ========================================
// PASO 2: IDENTIFICAR TIPO DE COMPONENTE
// ========================================

switch (prefijo)
{
    case "3RT":
    case "LC1":
    case "AF0":
    case "AF1":
    case "AF2":
    case "DIL":
        tipoComponente = "Contactor";
        break;
    case "3RV":
    case "PKZ":
        tipoComponente = "Guardamotor";
        break;
    case "3RA":
    case "LR2":
    case "AX0":
        tipoComponente = "Relé térmico";
        break;
    case "3RU":
        tipoComponente = "Relé de sobrecarga";
        break;
    case "GV2":
    case "GV3":
        tipoComponente = "Disyuntor motor";
        break;
    case "NZM":
        tipoComponente = "Interruptor automático caja moldeada";
        break;
    default:
        tipoComponente = "Componente no identificado";
        break;
}

Paso 4: Obtener especificaciones según código completo

// ========================================
// PASO 3: ESPECIFICACIONES POR CÓDIGO
// ========================================

switch (codigoArticulo)
{
    // Contactores Siemens 3RT20
    case "3RT2026-1BB40":
        descripcionCorta = "Contactor 3P 25A AC3";
        descripcionLarga = "Contactor tripolar, corriente nominal 25A en AC3, " +
                          "bobina 24V DC, 1NA+1NC auxiliar";
        especificacionesTecnicas =
            "- Corriente nominal: 25A (AC3)\n" +
            "- Polos principales: 3\n" +
            "- Bobina: 24V DC\n" +
            "- Contactos auxiliares: 1NA + 1NC\n" +
            "- Poder de corte: 18.5kW @ 400V\n" +
            "- Categoría: AC3 (motores)";
        break;

    case "3RT2036-1BB40":
        descripcionCorta = "Contactor 3P 40A AC3";
        descripcionLarga = "Contactor tripolar, corriente nominal 40A en AC3, " +
                          "bobina 24V DC, 1NA+1NC auxiliar";
        especificacionesTecnicas =
            "- Corriente nominal: 40A (AC3)\n" +
            "- Polos principales: 3\n" +
            "- Bobina: 24V DC\n" +
            "- Contactos auxiliares: 1NA + 1NC\n" +
            "- Poder de corte: 22kW @ 400V\n" +
            "- Categoría: AC3 (motores)";
        break;

    case "3RT2046-1BB40":
        descripcionCorta = "Contactor 3P 65A AC3";
        descripcionLarga = "Contactor tripolar, corriente nominal 65A en AC3, " +
                          "bobina 24V DC, 1NA+1NC auxiliar";
        especificacionesTecnicas =
            "- Corriente nominal: 65A (AC3)\n" +
            "- Polos principales: 3\n" +
            "- Bobina: 24V DC\n" +
            "- Contactos auxiliares: 1NA + 1NC\n" +
            "- Poder de corte: 37kW @ 400V\n" +
            "- Categoría: AC3 (motores)";
        break;

    // Guardamotores Siemens 3RV20
    case "3RV2011-1JA10":
        descripcionCorta = "Guardamotor 3.5-5A";
        descripcionLarga = "Guardamotor ajustable, rango 3.5-5A, " +
                          "disparo magnético 65A";
        especificacionesTecnicas =
            "- Rango ajuste: 3.5-5A\n" +
            "- Disparo magnético: 65A\n" +
            "- Poder de corte: 100kA @ 400V\n" +
            "- Clase disparo: Clase 10\n" +
            "- Contactos auxiliares: 1NA+1NC";
        break;

    case "3RV2021-4BA10":
        descripcionCorta = "Guardamotor 18-25A";
        descripcionLarga = "Guardamotor ajustable, rango 18-25A, " +
                          "disparo magnético 325A";
        especificacionesTecnicas =
            "- Rango ajuste: 18-25A\n" +
            "- Disparo magnético: 325A\n" +
            "- Poder de corte: 100kA @ 400V\n" +
            "- Clase disparo: Clase 10\n" +
            "- Contactos auxiliares: 1NA+1NC";
        break;

    // Contactores Schneider LC1D
    case "LC1D09BD":
        descripcionCorta = "Contactor 3P 9A AC3";
        descripcionLarga = "Contactor TeSys D, corriente nominal 9A en AC3, " +
                          "bobina 24V DC";
        especificacionesTecnicas =
            "- Corriente nominal: 9A (AC3)\n" +
            "- Polos principales: 3\n" +
            "- Bobina: 24V DC\n" +
            "- Contactos auxiliares: 1NA + 1NC\n" +
            "- Poder de corte: 4kW @ 400V\n" +
            "- Serie: TeSys D";
        break;

    case "LC1D18BD":
        descripcionCorta = "Contactor 3P 18A AC3";
        descripcionLarga = "Contactor TeSys D, corriente nominal 18A en AC3, " +
                          "bobina 24V DC";
        especificacionesTecnicas =
            "- Corriente nominal: 18A (AC3)\n" +
            "- Polos principales: 3\n" +
            "- Bobina: 24V DC\n" +
            "- Contactos auxiliares: 1NA + 1NC\n" +
            "- Poder de corte: 7.5kW @ 400V\n" +
            "- Serie: TeSys D";
        break;

    // Contactores ABB
    case "AF09-30-10-13":
        descripcionCorta = "Contactor 3P 9A AC3";
        descripcionLarga = "Contactor AF, corriente nominal 9A en AC3, " +
                          "bobina 100-250V AC/DC";
        especificacionesTecnicas =
            "- Corriente nominal: 9A (AC3)\n" +
            "- Polos principales: 3\n" +
            "- Bobina: 100-250V AC/DC\n" +
            "- Contactos auxiliares: 1NA\n" +
            "- Poder de corte: 4kW @ 400V\n" +
            "- Serie: AF";
        break;

    // Caso default
    default:
        descripcionCorta = "Código no encontrado en base de datos";
        descripcionLarga = string.Format(
            "El código '{0}' no está registrado en el configurador. " +
            "Consulte catálogo del fabricante.",
            codigoArticulo
        );
        especificacionesTecnicas = "No disponible";
        break;
}

¿Qué acabamos de hacer? Creamos una base de datos de componentes usando switch. Cada código de artículo tiene sus especificaciones completas.


Paso 5: Generar código de designación EPLAN

// ========================================
// PASO 4: GENERAR DESIGNACIÓN EPLAN
// ========================================

string prefijoDesignacion;

switch (tipoComponente)
{
    case "Contactor":
        prefijoDesignacion = "K";
        break;
    case "Guardamotor":
        prefijoDesignacion = "Q";
        break;
    case "Relé térmico":
    case "Relé de sobrecarga":
        prefijoDesignacion = "F";
        break;
    case "Disyuntor motor":
        prefijoDesignacion = "Q";
        break;
    case "Interruptor automático caja moldeada":
        prefijoDesignacion = "Q";
        break;
    default:
        prefijoDesignacion = "?";
        break;
}

string designacionSugerida = prefijoDesignacion + "1";  // Ejemplo: K1, Q1, F1

Paso 6: Construir reporte final

// ========================================
// CONSTRUCCIÓN DEL REPORTE
// ========================================

string separador = new string('=', 50);

string reporte = string.Format(
    "{0}\n" +
    "CONFIGURADOR DE COMPONENTES ELÉCTRICOS\n" +
    "{0}\n\n" +
    "CÓDIGO DE ARTÍCULO: {1}\n\n" +
    "IDENTIFICACIÓN:\n" +
    "- Fabricante: {2}\n" +
    "- Tipo: {3}\n" +
    "- Designación sugerida: {4}\n\n" +
    "DESCRIPCIÓN:\n" +
    "{5}\n\n" +
    "ESPECIFICACIONES TÉCNICAS:\n" +
    "{6}\n\n" +
    "{0}",
    separador,
    codigoArticulo,
    fabricante,
    tipoComponente,
    designacionSugerida,
    descripcionLarga,
    especificacionesTecnicas
);

// ========================================
// MOSTRAR REPORTE
// ========================================

MessageBoxIcon icono = (fabricante == "Fabricante no identificado")
    ? MessageBoxIcon.Warning
    : MessageBoxIcon.Information;

MessageBox.Show(reporte, "Configurador de Componentes", MessageBoxButtons.OK, icono);

Código completo del proyecto

using System;
using Eplan.EplApi.Base;
using Eplan.EplApi.ApplicationFramework;

public class ConfiguradorComponentes
{
    [Start]
    public void Ejecutar()
    {
        // ========================================
        // CÓDIGO DE ARTÍCULO A CONSULTAR
        // ========================================

        string codigoArticulo = "3RT2026-1BB40";

        // Variables para almacenar información
        string tipoComponente;
        string fabricante;
        string descripcionCorta;
        string descripcionLarga;
        string especificacionesTecnicas;

        // ========================================
        // PASO 1: IDENTIFICAR FABRICANTE
        // ========================================

        string prefijo = codigoArticulo.Substring(0, 3);

        switch (prefijo)
        {
            case "3RT":
            case "3RV":
            case "3RA":
            case "3RU":
                fabricante = "Siemens";
                break;
            case "LC1":
            case "LR2":
            case "GV2":
            case "GV3":
                fabricante = "Schneider Electric";
                break;
            case "AF0":
            case "AF1":
            case "AF2":
            case "AX0":
                fabricante = "ABB";
                break;
            case "DIL":
            case "PKZ":
            case "NZM":
                fabricante = "Eaton / Moeller";
                break;
            default:
                fabricante = "Fabricante no identificado";
                break;
        }

        // ========================================
        // PASO 2: IDENTIFICAR TIPO DE COMPONENTE
        // ========================================

        switch (prefijo)
        {
            case "3RT":
            case "LC1":
            case "AF0":
            case "AF1":
            case "AF2":
            case "DIL":
                tipoComponente = "Contactor";
                break;
            case "3RV":
            case "PKZ":
                tipoComponente = "Guardamotor";
                break;
            case "3RA":
            case "LR2":
            case "AX0":
                tipoComponente = "Relé térmico";
                break;
            case "3RU":
                tipoComponente = "Relé de sobrecarga";
                break;
            case "GV2":
            case "GV3":
                tipoComponente = "Disyuntor motor";
                break;
            case "NZM":
                tipoComponente = "Interruptor automático caja moldeada";
                break;
            default:
                tipoComponente = "Componente no identificado";
                break;
        }

        // ========================================
        // PASO 3: ESPECIFICACIONES POR CÓDIGO
        // ========================================

        switch (codigoArticulo)
        {
            // Contactores Siemens 3RT20
            case "3RT2026-1BB40":
                descripcionCorta = "Contactor 3P 25A AC3";
                descripcionLarga = "Contactor tripolar, corriente nominal 25A en AC3, " +
                                  "bobina 24V DC, 1NA+1NC auxiliar";
                especificacionesTecnicas =
                    "- Corriente nominal: 25A (AC3)\n" +
                    "- Polos principales: 3\n" +
                    "- Bobina: 24V DC\n" +
                    "- Contactos auxiliares: 1NA + 1NC\n" +
                    "- Poder de corte: 18.5kW @ 400V\n" +
                    "- Categoría: AC3 (motores)";
                break;

            case "3RT2036-1BB40":
                descripcionCorta = "Contactor 3P 40A AC3";
                descripcionLarga = "Contactor tripolar, corriente nominal 40A en AC3, " +
                                  "bobina 24V DC, 1NA+1NC auxiliar";
                especificacionesTecnicas =
                    "- Corriente nominal: 40A (AC3)\n" +
                    "- Polos principales: 3\n" +
                    "- Bobina: 24V DC\n" +
                    "- Contactos auxiliares: 1NA + 1NC\n" +
                    "- Poder de corte: 22kW @ 400V\n" +
                    "- Categoría: AC3 (motores)";
                break;

            case "3RT2046-1BB40":
                descripcionCorta = "Contactor 3P 65A AC3";
                descripcionLarga = "Contactor tripolar, corriente nominal 65A en AC3, " +
                                  "bobina 24V DC, 1NA+1NC auxiliar";
                especificacionesTecnicas =
                    "- Corriente nominal: 65A (AC3)\n" +
                    "- Polos principales: 3\n" +
                    "- Bobina: 24V DC\n" +
                    "- Contactos auxiliares: 1NA + 1NC\n" +
                    "- Poder de corte: 37kW @ 400V\n" +
                    "- Categoría: AC3 (motores)";
                break;

            // Guardamotores Siemens 3RV20
            case "3RV2011-1JA10":
                descripcionCorta = "Guardamotor 3.5-5A";
                descripcionLarga = "Guardamotor ajustable, rango 3.5-5A, " +
                                  "disparo magnético 65A";
                especificacionesTecnicas =
                    "- Rango ajuste: 3.5-5A\n" +
                    "- Disparo magnético: 65A\n" +
                    "- Poder de corte: 100kA @ 400V\n" +
                    "- Clase disparo: Clase 10\n" +
                    "- Contactos auxiliares: 1NA+1NC";
                break;

            case "3RV2021-4BA10":
                descripcionCorta = "Guardamotor 18-25A";
                descripcionLarga = "Guardamotor ajustable, rango 18-25A, " +
                                  "disparo magnético 325A";
                especificacionesTecnicas =
                    "- Rango ajuste: 18-25A\n" +
                    "- Disparo magnético: 325A\n" +
                    "- Poder de corte: 100kA @ 400V\n" +
                    "- Clase disparo: Clase 10\n" +
                    "- Contactos auxiliares: 1NA+1NC";
                break;

            // Contactores Schneider LC1D
            case "LC1D09BD":
                descripcionCorta = "Contactor 3P 9A AC3";
                descripcionLarga = "Contactor TeSys D, corriente nominal 9A en AC3, " +
                                  "bobina 24V DC";
                especificacionesTecnicas =
                    "- Corriente nominal: 9A (AC3)\n" +
                    "- Polos principales: 3\n" +
                    "- Bobina: 24V DC\n" +
                    "- Contactos auxiliares: 1NA + 1NC\n" +
                    "- Poder de corte: 4kW @ 400V\n" +
                    "- Serie: TeSys D";
                break;

            case "LC1D18BD":
                descripcionCorta = "Contactor 3P 18A AC3";
                descripcionLarga = "Contactor TeSys D, corriente nominal 18A en AC3, " +
                                  "bobina 24V DC";
                especificacionesTecnicas =
                    "- Corriente nominal: 18A (AC3)\n" +
                    "- Polos principales: 3\n" +
                    "- Bobina: 24V DC\n" +
                    "- Contactos auxiliares: 1NA + 1NC\n" +
                    "- Poder de corte: 7.5kW @ 400V\n" +
                    "- Serie: TeSys D";
                break;

            // Contactores ABB
            case "AF09-30-10-13":
                descripcionCorta = "Contactor 3P 9A AC3";
                descripcionLarga = "Contactor AF, corriente nominal 9A en AC3, " +
                                  "bobina 100-250V AC/DC";
                especificacionesTecnicas =
                    "- Corriente nominal: 9A (AC3)\n" +
                    "- Polos principales: 3\n" +
                    "- Bobina: 100-250V AC/DC\n" +
                    "- Contactos auxiliares: 1NA\n" +
                    "- Poder de corte: 4kW @ 400V\n" +
                    "- Serie: AF";
                break;

            // Caso default
            default:
                descripcionCorta = "Código no encontrado en base de datos";
                descripcionLarga = string.Format(
                    "El código '{0}' no está registrado en el configurador. " +
                    "Consulte catálogo del fabricante.",
                    codigoArticulo
                );
                especificacionesTecnicas = "No disponible";
                break;
        }

        // ========================================
        // PASO 4: GENERAR DESIGNACIÓN EPLAN
        // ========================================

        string prefijoDesignacion;

        switch (tipoComponente)
        {
            case "Contactor":
                prefijoDesignacion = "K";
                break;
            case "Guardamotor":
                prefijoDesignacion = "Q";
                break;
            case "Relé térmico":
            case "Relé de sobrecarga":
                prefijoDesignacion = "F";
                break;
            case "Disyuntor motor":
                prefijoDesignacion = "Q";
                break;
            case "Interruptor automático caja moldeada":
                prefijoDesignacion = "Q";
                break;
            default:
                prefijoDesignacion = "?";
                break;
        }

        string designacionSugerida = prefijoDesignacion + "1";

        // ========================================
        // CONSTRUCCIÓN DEL REPORTE
        // ========================================

        string separador = new string('=', 50);

        string reporte = string.Format(
            "{0}\n" +
            "CONFIGURADOR DE COMPONENTES ELÉCTRICOS\n" +
            "{0}\n\n" +
            "CÓDIGO DE ARTÍCULO: {1}\n\n" +
            "IDENTIFICACIÓN:\n" +
            "- Fabricante: {2}\n" +
            "- Tipo: {3}\n" +
            "- Designación sugerida: {4}\n\n" +
            "DESCRIPCIÓN:\n" +
            "{5}\n\n" +
            "ESPECIFICACIONES TÉCNICAS:\n" +
            "{6}\n\n" +
            "{0}",
            separador,
            codigoArticulo,
            fabricante,
            tipoComponente,
            designacionSugerida,
            descripcionLarga,
            especificacionesTecnicas
        );

        // ========================================
        // MOSTRAR REPORTE
        // ========================================

        MessageBoxIcon icono = (fabricante == "Fabricante no identificado")
            ? MessageBoxIcon.Warning
            : MessageBoxIcon.Information;

        MessageBox.Show(reporte, "Configurador de Componentes", MessageBoxButtons.OK, icono);
    }
}

Ejercicios:

  • Cambia codigoArticulo a "3RV2011-1JA10" (guardamotor)
  • Prueba con "LC1D18BD" (Schneider)
  • Prueba con "XXXX" (código no existente)
  • Agrega más componentes al switch

Deep Dive: Entendiendo en profundidad

Fall-through y goto case

En algunos lenguajes, si olvidas break, el código "cae" al siguiente caso (fall-through). En C#, esto es error de compilación para evitar bugs.

Pero puedes hacerlo explícitamente con goto case:

switch (codigo)
{
    case "A":
        MessageBox.Show("Procesando A");
        goto case "B";  // Continúa explícitamente en B
    case "B":
        MessageBox.Show("Procesando B");
        break;
}

Uso práctico (raro):

string tipoInstalacion = "Industrial";
string requisitosSeguirdad = "";

switch (tipoInstalacion)
{
    case "Industrial":
        requisitosSeguirdad += "- Señalización de emergencia\n";
        goto case "Comercial";
    case "Comercial":
        requisitosSeguirdad += "- Iluminación de emergencia\n";
        goto case "Residencial";
    case "Residencial":
        requisitosSeguirdad += "- Protección diferencial 30mA\n";
        break;
}
// Industrial tiene los 3 requisitos

Pero generalmente es mejor usar funciones o lógica clara.

Enums con switch

Los enum (enumeraciones) funcionan perfectamente con switch:

enum TipoProteccion
{
    TipoB,
    TipoC,
    TipoD
}

TipoProteccion tipo = TipoProteccion.TipoD;

switch (tipo)
{
    case TipoProteccion.TipoB:
        MessageBox.Show("Para iluminación");
        break;
    case TipoProteccion.TipoC:
        MessageBox.Show("Para uso general");
        break;
    case TipoProteccion.TipoD:
        MessageBox.Show("Para motores");
        break;
}

Lo veremos en detalle en capítulos posteriores.

Pattern matching (C# 7.0+)

Switch moderno permite patrones más complejos:

object obj = 25;

switch (obj)
{
    case int i when i < 16:
        MessageBox.Show("Entero menor a 16");
        break;
    case int i when i >= 16:
        MessageBox.Show("Entero mayor o igual a 16");
        break;
    case string s:
        MessageBox.Show("Es un string");
        break;
    default:
        MessageBox.Show("Otro tipo");
        break;
}

Mejores prácticas

1. Siempre incluye default

Aunque creas que cubriste todos los casos, siempre incluye default para casos inesperados.

2. Ordena los casos lógicamente

// Bien: orden lógico (de menor a mayor)
switch (corriente)
{
    case 10:
        // ...
    case 16:
        // ...
    case 20:
        // ...
    case 25:
        // ...
}

3. Usa constantes para valores repetidos

const string TIPO_MOTOR = "Motor";
const string TIPO_ILUMINACION = "Iluminacion";

switch (tipoCarga)
{
    case TIPO_MOTOR:
        // ...
    case TIPO_ILUMINACION:
        // ...
}

4. No abuses del switch para lógica compleja

Si cada caso tiene 20 líneas de código, considera usar funciones:

// Mal: casos con mucho código
switch (tipo)
{
    case "A":
        // 20 líneas de código...
        break;
    case "B":
        // 20 líneas de código...
        break;
}

// Mejor: delegar a funciones
switch (tipo)
{
    case "A":
        ProcesarTipoA();
        break;
    case "B":
        ProcesarTipoB();
        break;
}

Errores comunes

Error 1: Olvidar break

switch (tipo)
{
    case "A":
        MessageBox.Show("A");
        // Sin break - ERROR de compilación
    case "B":
        MessageBox.Show("B");
        break;
}

Solución: Siempre pon break, return, goto o throw.


Error 2: Usar variables no constantes en case

int limite = 16;

switch (corriente)
{
    case limite:  // ERROR: debe ser constante
        break;
}

Solución: Usa const o literal:

const int LIMITE = 16;

switch (corriente)
{
    case LIMITE:  // OK
        break;
}

Error 3: Usar tipos no soportados

double voltaje = 230.5;

switch (voltaje)  // ERROR: double no soportado
{
    case 230.0:
        break;
}

Solución: Usa if/else if para double/float.


Desafíos (Opcional)

Desafío 1: Convertidor de grados de protección IP a texto

Dificultad: Bajo

Crea un script que convierta códigos IP (20, 44, 54, 65, 67, 68) a descripciones completas incluyendo:

  • Protección contra sólidos
  • Protección contra líquidos
  • Aplicaciones típicas
Pista

Usa switch con el código IP completo y asigna descripciones detalladas a cada caso.


Desafío 2: Decodificador de designaciones IEC

Dificultad: Medio

Crea un script que identifique el tipo de componente por su letra de designación IEC:

  • K = Contactor, relé
  • Q = Interruptor, seccionador
  • F = Protección
  • M = Motor
  • T = Transformador
  • etc.

Y genere una descripción del propósito típico.


Desafío 3: Configurador de curvas de magnetotérmicos extendido

Dificultad: Alta

Crea un script completo que:

  1. Reciba: tipo de carga, corriente nominal, voltaje, número de polos
  2. Determine: curva de disparo (B/C/D/K/Z), corriente nominal, número de polos
  3. Genere: código de artículo automático en formato estándar
  4. Calcule: poder de corte necesario según instalación

Resumen

En este capítulo aprendiste:

  • Estructura switch: Comparar una variable contra múltiples valores constantes
  • Casos múltiples: Varios case ejecutando el mismo código
  • Caso default: Manejar valores no esperados
  • Cuándo usar switch vs if/else: Criterios de decisión
  • Switch expressions: Sintaxis moderna más compacta (C# 8.0+)
  • Proyecto construido: Configurador de componentes eléctricos con base de datos

Conceptos clave:

  • Switch es ideal para comparar una variable contra muchos valores específicos
  • Cada case debe terminar con break (o return/goto/throw)
  • El default es opcional pero muy recomendable
  • Solo funciona con int, string, char, enum, bool (no double/float)
  • Para rangos o condiciones complejas, usa if/else if

Recursos adicionales


Preguntas frecuentes

P: ¿Puedo usar switch con double o float?

R: No. Switch solo funciona con int, string, char, enum, bool. Para double/float usa if/else if.

P: ¿Qué pasa si olvido el break?

R: Error de compilación. C# obliga a terminar cada case con break, return, goto o throw.

P: ¿Cuándo usar switch expression vs switch tradicional?

R: Usa switch expression para asignaciones simples de una línea. Usa switch tradicional cuando cada caso necesita múltiples líneas de código.

P: ¿Puedo tener un case vacío?

R: Sí, para agrupar casos:

case "A":
case "B":
    // Código para ambos
    break;

P: ¿El orden de los cases importa?

R: No afecta la funcionalidad, pero ordénalos lógicamente para legibilidad.


Checklist de completitud

Antes de pasar al siguiente capítulo, asegúrate de:

  • Entender la sintaxis básica de switch
  • Saber cuándo usar switch vs if/else if
  • Poder agrupar múltiples cases
  • Siempre incluir break en cada case
  • Usar default para casos no previstos
  • Conocer las limitaciones de switch (tipos soportados)
  • Haber ejecutado exitosamente el configurador de componentes
  • Poder agregar nuevos componentes al switch
  • (Opcional) Conocer switch expressions
  • (Opcional) Haber intentado al menos un desafío

Última actualización: Enero 2025 Tiempo de lectura estimado: 40-50 minutos Código de ejemplo: code/cap-06/