Capítulo 5: Condicionales if/else en C#
5 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 if/else para ejecutar código condicionalmente
- Encadenar condiciones con else if para múltiples casos
- Anidar estructuras if dentro de otras
- Aplicar el operador ternario para asignaciones condicionales simples
- Construir lógica de decisión para selección automática de componentes eléctricos
Requisitos previos
Antes de comenzar este capítulo debes:
- Haber completado el Capítulo 4
- Entender operadores de comparación (==, !=, >, <, >=, <=)
- Entender operadores lógicos (&&, ||, !)
- Saber construir expresiones booleanas
Proyecto del capítulo
Selector Automático de Protecciones Eléctricas
Al final de este capítulo habrás construido un script que:
- Selecciona automáticamente el interruptor magnetotérmico adecuado
- Determina la sección de cable necesaria
- Calcula el tipo de protección diferencial requerida
- Genera especificaciones técnicas completas
Tiempo estimado: 45-55 minutos
Contenido
1. Introducción: Tomar decisiones en el código
Hasta ahora, nuestros scripts ejecutaban todas las líneas secuencialmente, de arriba a abajo. Pero en la vida real, necesitamos tomar decisiones:
- "Si el voltaje es mayor a 253V, entonces mostrar una alerta"
- "Si la corriente excede 16A, entonces seleccionar un cable más grueso, si no, usar el cable estándar"
- "Si es circuito de iluminación, usar protección tipo B; si es motor, usar tipo D"
La estructura if/else te permite ejecutar diferentes bloques de código según condiciones.
2. La estructura if básica
La sintaxis más simple:
if (condicion)
{
// Código que se ejecuta si la condición es true
}
Ejemplo práctico:
double voltaje = 260.0;
if (voltaje > 253.0)
{
MessageBox.Show("Advertencia: Voltaje excesivo detectado.");
}
Flujo de ejecución:
- Se evalúa la condición
voltaje > 253.0 - Si es
true, se ejecuta el bloque entre{ } - Si es
false, se salta el bloque y continúa después
2.1 Anatomía del if
if (condicion)
↑ ↑
| └─ Expresión booleana (true/false)
└────────── Palabra clave
{
// Bloque de código
// Puede tener múltiples líneas
}
2.2 Ejemplos prácticos
Ejemplo 1: Validar corriente
double corriente = 18.5;
double corrienteMaxima = 16.0;
if (corriente > corrienteMaxima)
{
MessageBox.Show("La corriente excede el límite permitido.");
}
Ejemplo 2: Verificar proyecto abierto
bool proyectoAbierto = true;
if (proyectoAbierto)
{
// Procesar el proyecto
MessageBox.Show("Procesando proyecto...");
}
Ejemplo 3: Condición compuesta
double voltaje = 195.0;
double voltajeMinimo = 207.0;
double voltajeMaximo = 253.0;
if (voltaje < voltajeMinimo || voltaje > voltajeMaximo)
{
MessageBox.Show("Voltaje fuera del rango permitido (207V - 253V).");
}
2.3 If de una línea (sin llaves)
Si solo hay una instrucción, puedes omitir las llaves:
if (voltaje > 253.0)
MessageBox.Show("Voltaje alto");
Pero no es recomendable porque:
- Es fácil agregar otra línea y olvidar las llaves
- Reduce la legibilidad
Mejor práctica: Siempre usa llaves, incluso para una línea:
if (voltaje > 253.0)
{
MessageBox.Show("Voltaje alto");
}
3. La estructura if/else
Para ejecutar un código cuando la condición es true y otro cuando es false:
if (condicion)
{
// Se ejecuta si condicion es true
}
else
{
// Se ejecuta si condicion es false
}
Ejemplo práctico:
double corriente = 14.5;
double corrienteMaxima = 16.0;
if (corriente <= corrienteMaxima)
{
MessageBox.Show("Corriente dentro de límites normales.");
}
else
{
MessageBox.Show("Corriente excede el límite. Revisar instalación.");
}
3.1 Flujo de ejecución
┌─────────────┐
│ if (cond) │
└──────┬──────┘
│
┌──────┴──────┐
│ │
true false
│ │
┌───▼───┐ ┌───▼───┐
│ if {} │ │else {} │
└───┬───┘ └───┬───┘
│ │
└──────┬──────┘
│
continúa
Solo uno de los dos bloques se ejecuta, nunca ambos.
3.2 Ejemplos prácticos
Ejemplo 1: Clasificar proyecto por tamaño
int numeroPaginas = 45;
if (numeroPaginas <= 20)
{
MessageBox.Show("Proyecto pequeño (hasta 20 páginas).");
}
else
{
MessageBox.Show("Proyecto grande (más de 20 páginas).");
}
Ejemplo 2: Seleccionar tipo de cable
bool ambienteHumedo = true;
if (ambienteHumedo)
{
MessageBox.Show("Usar cable tipo H07RN-F (resistente a humedad).");
}
else
{
MessageBox.Show("Usar cable tipo H07V-K (instalación estándar).");
}
Ejemplo 3: Determinar tipo de sistema
double voltaje = 400.0;
if (voltaje > 380.0)
{
MessageBox.Show("Sistema trifásico (400V).");
}
else
{
MessageBox.Show("Sistema monofásico (230V).");
}
4. La estructura else if - múltiples condiciones
Cuando tienes más de dos casos posibles:
if (condicion1)
{
// Se ejecuta si condicion1 es true
}
else if (condicion2)
{
// Se ejecuta si condicion1 es false y condicion2 es true
}
else if (condicion3)
{
// Se ejecuta si condicion1 y condicion2 son false, y condicion3 es true
}
else
{
// Se ejecuta si ninguna condición anterior es true
}
Importante: Se evalúan en orden. El primer if o else if que sea true se ejecuta, y se salta el resto.
4.1 Ejemplo práctico: Clasificar sección de cable
double corriente = 25.0;
string seccionRecomendada;
if (corriente <= 16.0)
{
seccionRecomendada = "2.5 mm²";
}
else if (corriente <= 20.0)
{
seccionRecomendada = "4 mm²";
}
else if (corriente <= 25.0)
{
seccionRecomendada = "6 mm²";
}
else if (corriente <= 32.0)
{
seccionRecomendada = "10 mm²";
}
else
{
seccionRecomendada = "Requiere cálculo específico (> 32A)";
}
MessageBox.Show("Sección recomendada: " + seccionRecomendada);
4.2 Ejemplo: Clasificar factor de potencia
double factorPotencia = 0.78;
string clasificacion;
if (factorPotencia >= 0.95)
{
clasificacion = "Excelente - No requiere corrección";
}
else if (factorPotencia >= 0.90)
{
clasificacion = "Bueno - Corrección opcional";
}
else if (factorPotencia >= 0.85)
{
clasificacion = "Aceptable - Corrección recomendada";
}
else
{
clasificacion = "Bajo - Corrección necesaria";
}
string mensaje = string.Format(
"Factor de potencia: {0:F2}\nClasificación: {1}",
factorPotencia,
clasificacion
);
MessageBox.Show(mensaje);
4.3 Flujo de ejecución con else if
if (cond1)?
├─ true → ejecuta bloque 1 → FIN
└─ false → else if (cond2)?
├─ true → ejecuta bloque 2 → FIN
└─ false → else if (cond3)?
├─ true → ejecuta bloque 3 → FIN
└─ false → else (bloque 4) → FIN
Solo uno de los bloques se ejecuta.
5. If anidados (nested if)
Puedes colocar un if dentro de otro:
if (condicionExterna)
{
// Código nivel 1
if (condicionInterna)
{
// Código nivel 2
}
}
5.1 Ejemplo práctico: Validación de circuito completo
double voltaje = 230.0;
double corriente = 15.5;
// Verificación nivel 1: Voltaje
if (voltaje >= 207.0 && voltaje <= 253.0)
{
MessageBox.Show("Voltaje OK");
// Verificación nivel 2: Corriente (solo si voltaje OK)
if (corriente <= 16.0)
{
MessageBox.Show("Corriente OK\nCircuito completamente validado.");
}
else
{
MessageBox.Show("Corriente excesiva. Revisar.");
}
}
else
{
MessageBox.Show("Voltaje fuera de rango. No se verificó la corriente.");
}
5.2 Ejemplo: Selección de protección diferencial
string tipoCarga = "Motor"; // Opciones: "Iluminacion", "Motor", "Informatica"
double corriente = 20.0;
if (tipoCarga == "Motor")
{
// Motores requieren Tipo A (sensibles a CC)
if (corriente <= 25.0)
{
MessageBox.Show("Diferencial: Tipo A, 30mA, 25A");
}
else if (corriente <= 40.0)
{
MessageBox.Show("Diferencial: Tipo A, 30mA, 40A");
}
else
{
MessageBox.Show("Diferencial: Tipo A, 300mA, 63A o superior");
}
}
else if (tipoCarga == "Informatica")
{
// Informática requiere Tipo B (sensibles a CC y alta frecuencia)
MessageBox.Show("Diferencial: Tipo B, 30mA, corriente según carga");
}
else
{
// Iluminación y otros: Tipo AC estándar
if (corriente <= 25.0)
{
MessageBox.Show("Diferencial: Tipo AC, 30mA, 25A");
}
else
{
MessageBox.Show("Diferencial: Tipo AC, 30mA, 40A");
}
}
5.3 Cuidado con la complejidad
Demasiados niveles de anidación reducen la legibilidad:
// Mal: demasiado anidado (difícil de leer)
if (condicion1)
{
if (condicion2)
{
if (condicion3)
{
if (condicion4)
{
// ¿Qué condiciones deben cumplirse para llegar aquí?
}
}
}
}
Mejor: Usa operadores lógicos para combinar condiciones:
// Bien: claro y directo
if (condicion1 && condicion2 && condicion3 && condicion4)
{
// Claramente se necesitan las 4 condiciones
}
O divide en funciones (lo veremos en capítulos futuros).
6. Operador ternario (? :)
Para asignaciones condicionales simples, existe un atajo:
variable = condicion ? valorSiTrue : valorSiFalse;
Es equivalente a:
if (condicion)
{
variable = valorSiTrue;
}
else
{
variable = valorSiFalse;
}
6.1 Ejemplos prácticos
Ejemplo 1: Determinar tipo de sistema
double voltaje = 400.0;
string tipoSistema = (voltaje > 300) ? "Trifásico" : "Monofásico";
// tipoSistema = "Trifásico"
Ejemplo 2: Clasificar proyecto
int numeroPaginas = 15;
string tamaño = (numeroPaginas <= 20) ? "Pequeño" : "Grande";
// tamaño = "Pequeño"
Ejemplo 3: Determinar estado
bool tieneErrores = false;
string estado = tieneErrores ? "Con errores" : "Sin errores";
// estado = "Sin errores"
6.2 Ternarios anidados (usar con precaución)
Puedes anidar operadores ternarios, pero reduce la legibilidad:
double corriente = 22.0;
string seccion = (corriente <= 16) ? "2.5mm²" :
(corriente <= 20) ? "4mm²" :
(corriente <= 25) ? "6mm²" : "10mm²";
Para casos complejos, usa if/else if:
string seccion;
if (corriente <= 16)
{
seccion = "2.5mm²";
}
else if (corriente <= 20)
{
seccion = "4mm²";
}
else if (corriente <= 25)
{
seccion = "6mm²";
}
else
{
seccion = "10mm²";
}
6.3 Cuándo usar el operador ternario
Usa ternario para:
- Asignaciones simples con dos opciones
- Casos donde mejora la concisión sin sacrificar claridad
Usa if/else para:
- Múltiples líneas de código en cada rama
- Más de dos opciones
- Cuando la legibilidad es más importante que la brevedad
7. Comparación de strings
Comparar textos requiere cuidado especial:
7.1 Comparación exacta (sensible a mayúsculas)
string tipo = "Motor";
if (tipo == "Motor")
{
MessageBox.Show("Tipo Motor detectado");
}
// Coincide: "Motor" == "Motor"
string tipo = "motor"; // Minúsculas
if (tipo == "Motor") // No coincide
{
// No entra aquí
}
7.2 Comparación insensible a mayúsculas
string tipo = "motor";
if (tipo.ToLower() == "motor") // Convierte a minúsculas
{
MessageBox.Show("Tipo Motor detectado");
// Ahora sí coincide
}
O mejor aún:
string tipo = "MOTOR";
if (tipo.Equals("motor", StringComparison.OrdinalIgnoreCase))
{
MessageBox.Show("Tipo Motor detectado");
// Coincide independientemente de mayúsculas
}
7.3 Ejemplo práctico completo
string tipoCargaInput = "motor"; // Usuario escribió en minúsculas
if (tipoCargaInput.Equals("Motor", StringComparison.OrdinalIgnoreCase))
{
MessageBox.Show("Protección Tipo D (arranque de motores)");
}
else if (tipoCargaInput.Equals("Iluminacion", StringComparison.OrdinalIgnoreCase))
{
MessageBox.Show("Protección Tipo B (iluminación)");
}
else if (tipoCargaInput.Equals("General", StringComparison.OrdinalIgnoreCase))
{
MessageBox.Show("Protección Tipo C (uso general)");
}
else
{
MessageBox.Show("Tipo de carga no reconocido");
}
Manos a la obra: Construyendo el proyecto
Vamos a crear un Selector Automático de Protecciones Eléctricas.
Paso 1: Estructura básica y entrada de datos
using System;
using Eplan.EplApi.Base;
using Eplan.EplApi.ApplicationFramework;
public class SelectorProtecciones
{
[Start]
public void Ejecutar()
{
// ========================================
// DATOS DEL CIRCUITO
// ========================================
string nombreCircuito = "Línea producción - Zona 2";
string tipoCarga = "Motor"; // Opciones: "Iluminacion", "Motor", "Tomas", "Informatica"
double corrienteNominal = 18.5; // Amperios
double longitudCable = 42.0; // Metros
bool ambienteHumedo = false;
double voltajeNominal = 230.0; // Voltios
}
}
Paso 2: Selección de curva de disparo (magnetotérmico)
// ========================================
// PASO 1: SELECCIONAR CURVA DE DISPARO
// ========================================
string curvaDisparo;
string justificacionCurva;
if (tipoCarga.Equals("Motor", StringComparison.OrdinalIgnoreCase))
{
curvaDisparo = "Curva D";
justificacionCurva = "Motores tienen alta corriente de arranque (6-8x In)";
}
else if (tipoCarga.Equals("Iluminacion", StringComparison.OrdinalIgnoreCase))
{
curvaDisparo = "Curva B";
justificacionCurva = "Iluminación tiene bajo pico de arranque";
}
else if (tipoCarga.Equals("Informatica", StringComparison.OrdinalIgnoreCase))
{
curvaDisparo = "Curva C";
justificacionCurva = "Equipos informáticos tienen pico moderado";
}
else
{
// Tomas y uso general
curvaDisparo = "Curva C";
justificacionCurva = "Uso general y tomas de corriente";
}
¿Qué acabamos de hacer? Seleccionamos la curva de disparo apropiada según el tipo de carga. Cada tipo requiere diferente sensibilidad para evitar disparos innecesarios.
Paso 3: Selección de corriente nominal del magnetotérmico
// ========================================
// PASO 2: SELECCIONAR CORRIENTE NOMINAL
// ========================================
int corrienteMagnetotermico;
if (corrienteNominal <= 10.0)
{
corrienteMagnetotermico = 10;
}
else if (corrienteNominal <= 16.0)
{
corrienteMagnetotermico = 16;
}
else if (corrienteNominal <= 20.0)
{
corrienteMagnetotermico = 20;
}
else if (corrienteNominal <= 25.0)
{
corrienteMagnetotermico = 25;
}
else if (corrienteNominal <= 32.0)
{
corrienteMagnetotermico = 32;
}
else if (corrienteNominal <= 40.0)
{
corrienteMagnetotermico = 40;
}
else
{
corrienteMagnetotermico = 63;
}
double margenProteccion = ((corrienteMagnetotermico - corrienteNominal) / corrienteNominal) * 100;
¿Qué acabamos de hacer? Seleccionamos el valor normalizado de corriente inmediatamente superior a la corriente nominal del circuito.
Paso 4: Selección de sección de cable
// ========================================
// PASO 3: SELECCIONAR SECCIÓN DE CABLE
// ========================================
double seccionCable;
double corrienteAdmisible;
// Tabla simplificada de corrientes admisibles (instalación tipo B)
if (corrienteMagnetotermico <= 10)
{
seccionCable = 1.5;
corrienteAdmisible = 15.0;
}
else if (corrienteMagnetotermico <= 16)
{
seccionCable = 2.5;
corrienteAdmisible = 21.0;
}
else if (corrienteMagnetotermico <= 20)
{
seccionCable = 4.0;
corrienteAdmisible = 27.0;
}
else if (corrienteMagnetotermico <= 25)
{
seccionCable = 6.0;
corrienteAdmisible = 36.0;
}
else if (corrienteMagnetotermico <= 32)
{
seccionCable = 10.0;
corrienteAdmisible = 50.0;
}
else if (corrienteMagnetotermico <= 40)
{
seccionCable = 16.0;
corrienteAdmisible = 68.0;
}
else
{
seccionCable = 25.0;
corrienteAdmisible = 89.0;
}
// Validar que el cable soporte la corriente del magnetotérmico
bool cableSuficiente = (corrienteAdmisible >= corrienteMagnetotermico);
¿Qué acabamos de hacer? Seleccionamos la sección de cable que puede soportar la corriente del magnetotérmico, siguiendo tablas de corrientes admisibles.
Paso 5: Selección de tipo de cable según ambiente
// ========================================
// PASO 4: SELECCIONAR TIPO DE CABLE
// ========================================
string tipoCable;
string descripcionCable;
if (ambienteHumedo)
{
tipoCable = "H07RN-F";
descripcionCable = "Cable flexible resistente a humedad y aceites";
}
else
{
tipoCable = "H07V-K";
descripcionCable = "Cable flexible para instalación estándar";
}
Paso 6: Cálculo de caída de tensión
// ========================================
// PASO 5: CALCULAR CAÍDA DE TENSIÓN
// ========================================
double resistividadCobre = 0.018; // Ω·mm²/m
double caidaTension = (2 * longitudCable * corrienteNominal * resistividadCobre) / seccionCable;
double porcentajeCaida = (caidaTension / voltajeNominal) * 100;
bool caidaAceptable = (porcentajeCaida <= 3.0);
string advertenciaCaida = "";
if (!caidaAceptable)
{
advertenciaCaida = "\n¡ADVERTENCIA! Caída de tensión excede 3%";
// Sugerir sección superior
double seccionSuperior = seccionCable;
if (seccionCable == 1.5) seccionSuperior = 2.5;
else if (seccionCable == 2.5) seccionSuperior = 4.0;
else if (seccionCable == 4.0) seccionSuperior = 6.0;
else if (seccionCable == 6.0) seccionSuperior = 10.0;
else if (seccionCable == 10.0) seccionSuperior = 16.0;
else if (seccionCable == 16.0) seccionSuperior = 25.0;
advertenciaCaida += string.Format("\nConsiderar sección {0}mm²", seccionSuperior);
}
¿Qué acabamos de hacer? Calculamos la caída de tensión y verificamos que esté bajo el 3%. Si no, sugerimos una sección superior.
Paso 7: Selección de diferencial
// ========================================
// PASO 6: SELECCIONAR DIFERENCIAL
// ========================================
string tipoDiferencial;
int sensibilidadDiferencial; // mA
int corrienteDiferencial;
// Tipo de diferencial según carga
if (tipoCarga.Equals("Motor", StringComparison.OrdinalIgnoreCase))
{
tipoDiferencial = "Tipo A"; // Sensible a corriente alterna y continua pulsante
}
else if (tipoCarga.Equals("Informatica", StringComparison.OrdinalIgnoreCase))
{
tipoDiferencial = "Tipo B"; // Sensible a corriente continua
}
else
{
tipoDiferencial = "Tipo AC"; // Sensible a corriente alterna (estándar)
}
// Sensibilidad según ambiente
if (ambienteHumedo)
{
sensibilidadDiferencial = 30; // Alta sensibilidad en ambiente húmedo
}
else
{
if (corrienteMagnetotermico > 32)
{
sensibilidadDiferencial = 300; // Menor sensibilidad para altas corrientes
}
else
{
sensibilidadDiferencial = 30;
}
}
// Corriente nominal del diferencial (debe ser >= magnetotérmico)
if (corrienteMagnetotermico <= 25)
{
corrienteDiferencial = 25;
}
else if (corrienteMagnetotermico <= 40)
{
corrienteDiferencial = 40;
}
else
{
corrienteDiferencial = 63;
}
¿Qué acabamos de hacer? Seleccionamos el tipo de diferencial según la carga, la sensibilidad según el ambiente, y la corriente nominal.
Paso 8: Construcción del reporte final
// ========================================
// CONSTRUCCIÓN DEL REPORTE
// ========================================
string reporte = string.Format(
"=== SELECTOR AUTOMÁTICO DE PROTECCIONES ===\n\n" +
"DATOS DEL CIRCUITO:\n" +
"- Nombre: {0}\n" +
"- Tipo de carga: {1}\n" +
"- Corriente nominal: {2:F1} A\n" +
"- Longitud: {3:F1} m\n" +
"- Ambiente húmedo: {4}\n\n" +
"PROTECCIÓN MAGNETOTÉRMICA:\n" +
"- {5} - {6}A\n" +
"- Justificación: {7}\n" +
"- Margen: {8:F1}%\n\n" +
"CABLE:\n" +
"- Tipo: {9}\n" +
"- Sección: {10}mm²\n" +
"- Descripción: {11}\n" +
"- Corriente admisible: {12:F1}A\n\n" +
"PROTECCIÓN DIFERENCIAL:\n" +
"- {13} - {14}mA - {15}A\n\n" +
"CAÍDA DE TENSIÓN:\n" +
"- Calculada: {16:F2}V ({17:F2}%)\n" +
"- Estado: {18}{19}",
nombreCircuito,
tipoCarga,
corrienteNominal,
longitudCable,
ambienteHumedo ? "Sí" : "No",
curvaDisparo,
corrienteMagnetotermico,
justificacionCurva,
margenProteccion,
tipoCable,
seccionCable,
descripcionCable,
corrienteAdmisible,
tipoDiferencial,
sensibilidadDiferencial,
corrienteDiferencial,
caidaTension,
porcentajeCaida,
caidaAceptable ? "Aceptable (< 3%)" : "Excesiva (> 3%)",
advertenciaCaida
);
// ========================================
// MOSTRAR REPORTE
// ========================================
MessageBoxIcon icono = caidaAceptable ? MessageBoxIcon.Information : MessageBoxIcon.Warning;
MessageBox.Show(reporte, "Selector de Protecciones", MessageBoxButtons.OK, icono);
Código completo del proyecto
using System;
using Eplan.EplApi.Base;
using Eplan.EplApi.ApplicationFramework;
public class SelectorProtecciones
{
[Start]
public void Ejecutar()
{
// ========================================
// DATOS DEL CIRCUITO
// ========================================
string nombreCircuito = "Línea producción - Zona 2";
string tipoCarga = "Motor"; // Opciones: "Iluminacion", "Motor", "Tomas", "Informatica"
double corrienteNominal = 18.5; // Amperios
double longitudCable = 42.0; // Metros
bool ambienteHumedo = false;
double voltajeNominal = 230.0; // Voltios
// ========================================
// PASO 1: SELECCIONAR CURVA DE DISPARO
// ========================================
string curvaDisparo;
string justificacionCurva;
if (tipoCarga.Equals("Motor", StringComparison.OrdinalIgnoreCase))
{
curvaDisparo = "Curva D";
justificacionCurva = "Motores tienen alta corriente de arranque (6-8x In)";
}
else if (tipoCarga.Equals("Iluminacion", StringComparison.OrdinalIgnoreCase))
{
curvaDisparo = "Curva B";
justificacionCurva = "Iluminación tiene bajo pico de arranque";
}
else if (tipoCarga.Equals("Informatica", StringComparison.OrdinalIgnoreCase))
{
curvaDisparo = "Curva C";
justificacionCurva = "Equipos informáticos tienen pico moderado";
}
else
{
// Tomas y uso general
curvaDisparo = "Curva C";
justificacionCurva = "Uso general y tomas de corriente";
}
// ========================================
// PASO 2: SELECCIONAR CORRIENTE NOMINAL
// ========================================
int corrienteMagnetotermico;
if (corrienteNominal <= 10.0)
{
corrienteMagnetotermico = 10;
}
else if (corrienteNominal <= 16.0)
{
corrienteMagnetotermico = 16;
}
else if (corrienteNominal <= 20.0)
{
corrienteMagnetotermico = 20;
}
else if (corrienteNominal <= 25.0)
{
corrienteMagnetotermico = 25;
}
else if (corrienteNominal <= 32.0)
{
corrienteMagnetotermico = 32;
}
else if (corrienteNominal <= 40.0)
{
corrienteMagnetotermico = 40;
}
else
{
corrienteMagnetotermico = 63;
}
double margenProteccion = ((corrienteMagnetotermico - corrienteNominal) / corrienteNominal) * 100;
// ========================================
// PASO 3: SELECCIONAR SECCIÓN DE CABLE
// ========================================
double seccionCable;
double corrienteAdmisible;
// Tabla simplificada de corrientes admisibles (instalación tipo B)
if (corrienteMagnetotermico <= 10)
{
seccionCable = 1.5;
corrienteAdmisible = 15.0;
}
else if (corrienteMagnetotermico <= 16)
{
seccionCable = 2.5;
corrienteAdmisible = 21.0;
}
else if (corrienteMagnetotermico <= 20)
{
seccionCable = 4.0;
corrienteAdmisible = 27.0;
}
else if (corrienteMagnetotermico <= 25)
{
seccionCable = 6.0;
corrienteAdmisible = 36.0;
}
else if (corrienteMagnetotermico <= 32)
{
seccionCable = 10.0;
corrienteAdmisible = 50.0;
}
else if (corrienteMagnetotermico <= 40)
{
seccionCable = 16.0;
corrienteAdmisible = 68.0;
}
else
{
seccionCable = 25.0;
corrienteAdmisible = 89.0;
}
// Validar que el cable soporte la corriente del magnetotérmico
bool cableSuficiente = (corrienteAdmisible >= corrienteMagnetotermico);
// ========================================
// PASO 4: SELECCIONAR TIPO DE CABLE
// ========================================
string tipoCable;
string descripcionCable;
if (ambienteHumedo)
{
tipoCable = "H07RN-F";
descripcionCable = "Cable flexible resistente a humedad y aceites";
}
else
{
tipoCable = "H07V-K";
descripcionCable = "Cable flexible para instalación estándar";
}
// ========================================
// PASO 5: CALCULAR CAÍDA DE TENSIÓN
// ========================================
double resistividadCobre = 0.018; // Ω·mm²/m
double caidaTension = (2 * longitudCable * corrienteNominal * resistividadCobre) / seccionCable;
double porcentajeCaida = (caidaTension / voltajeNominal) * 100;
bool caidaAceptable = (porcentajeCaida <= 3.0);
string advertenciaCaida = "";
if (!caidaAceptable)
{
advertenciaCaida = "\n¡ADVERTENCIA! Caída de tensión excede 3%";
// Sugerir sección superior
double seccionSuperior = seccionCable;
if (seccionCable == 1.5) seccionSuperior = 2.5;
else if (seccionCable == 2.5) seccionSuperior = 4.0;
else if (seccionCable == 4.0) seccionSuperior = 6.0;
else if (seccionCable == 6.0) seccionSuperior = 10.0;
else if (seccionCable == 10.0) seccionSuperior = 16.0;
else if (seccionCable == 16.0) seccionSuperior = 25.0;
advertenciaCaida += string.Format("\nConsiderar sección {0}mm²", seccionSuperior);
}
// ========================================
// PASO 6: SELECCIONAR DIFERENCIAL
// ========================================
string tipoDiferencial;
int sensibilidadDiferencial; // mA
int corrienteDiferencial;
// Tipo de diferencial según carga
if (tipoCarga.Equals("Motor", StringComparison.OrdinalIgnoreCase))
{
tipoDiferencial = "Tipo A"; // Sensible a corriente alterna y continua pulsante
}
else if (tipoCarga.Equals("Informatica", StringComparison.OrdinalIgnoreCase))
{
tipoDiferencial = "Tipo B"; // Sensible a corriente continua
}
else
{
tipoDiferencial = "Tipo AC"; // Sensible a corriente alterna (estándar)
}
// Sensibilidad según ambiente
if (ambienteHumedo)
{
sensibilidadDiferencial = 30; // Alta sensibilidad en ambiente húmedo
}
else
{
if (corrienteMagnetotermico > 32)
{
sensibilidadDiferencial = 300; // Menor sensibilidad para altas corrientes
}
else
{
sensibilidadDiferencial = 30;
}
}
// Corriente nominal del diferencial (debe ser >= magnetotérmico)
if (corrienteMagnetotermico <= 25)
{
corrienteDiferencial = 25;
}
else if (corrienteMagnetotermico <= 40)
{
corrienteDiferencial = 40;
}
else
{
corrienteDiferencial = 63;
}
// ========================================
// CONSTRUCCIÓN DEL REPORTE
// ========================================
string reporte = string.Format(
"=== SELECTOR AUTOMÁTICO DE PROTECCIONES ===\n\n" +
"DATOS DEL CIRCUITO:\n" +
"- Nombre: {0}\n" +
"- Tipo de carga: {1}\n" +
"- Corriente nominal: {2:F1} A\n" +
"- Longitud: {3:F1} m\n" +
"- Ambiente húmedo: {4}\n\n" +
"PROTECCIÓN MAGNETOTÉRMICA:\n" +
"- {5} - {6}A\n" +
"- Justificación: {7}\n" +
"- Margen: {8:F1}%\n\n" +
"CABLE:\n" +
"- Tipo: {9}\n" +
"- Sección: {10}mm²\n" +
"- Descripción: {11}\n" +
"- Corriente admisible: {12:F1}A\n\n" +
"PROTECCIÓN DIFERENCIAL:\n" +
"- {13} - {14}mA - {15}A\n\n" +
"CAÍDA DE TENSIÓN:\n" +
"- Calculada: {16:F2}V ({17:F2}%)\n" +
"- Estado: {18}{19}",
nombreCircuito,
tipoCarga,
corrienteNominal,
longitudCable,
ambienteHumedo ? "Sí" : "No",
curvaDisparo,
corrienteMagnetotermico,
justificacionCurva,
margenProteccion,
tipoCable,
seccionCable,
descripcionCable,
corrienteAdmisible,
tipoDiferencial,
sensibilidadDiferencial,
corrienteDiferencial,
caidaTension,
porcentajeCaida,
caidaAceptable ? "Aceptable (< 3%)" : "Excesiva (> 3%)",
advertenciaCaida
);
// ========================================
// MOSTRAR REPORTE
// ========================================
MessageBoxIcon icono = caidaAceptable ? MessageBoxIcon.Information : MessageBoxIcon.Warning;
MessageBox.Show(reporte, "Selector de Protecciones", MessageBoxButtons.OK, icono);
}
}
Deep Dive: Entendiendo en profundidad
Alcance de variables en bloques if
Las variables declaradas dentro de un bloque if solo existen dentro de ese bloque:
if (corriente > 16.0)
{
string mensaje = "Corriente alta";
MessageBox.Show(mensaje); // OK
}
MessageBox.Show(mensaje); // ERROR: 'mensaje' no existe aquí
Solución: Declara la variable antes del if:
string mensaje;
if (corriente > 16.0)
{
mensaje = "Corriente alta";
}
else
{
mensaje = "Corriente normal";
}
MessageBox.Show(mensaje); // OK
Switch como alternativa a else if
Para comparar una variable contra múltiples valores, switch puede ser más legible (lo veremos en el próximo capítulo):
// Con else if
if (tipoCarga == "Motor")
{
curva = "D";
}
else if (tipoCarga == "Iluminacion")
{
curva = "B";
}
else
{
curva = "C";
}
// Con switch (más limpio)
switch (tipoCarga)
{
case "Motor":
curva = "D";
break;
case "Iluminacion":
curva = "B";
break;
default:
curva = "C";
break;
}
Patrón Guard Clause
Para evitar anidación profunda, valida condiciones negativas primero y retorna/salta:
// Con anidación (difícil de leer)
if (proyectoAbierto)
{
if (tienePermisos)
{
if (noHayErrores)
{
// Código principal
}
}
}
// Con guard clauses (más claro)
if (!proyectoAbierto)
{
MessageBox.Show("Proyecto no abierto");
return;
}
if (!tienePermisos)
{
MessageBox.Show("Sin permisos");
return;
}
if (hayErrores)
{
MessageBox.Show("Proyecto con errores");
return;
}
// Código principal (sin anidación)
Mejores prácticas
1. Condiciones positivas son más legibles
// Menos claro
if (!(!esValido))
{
// ...
}
// Más claro
if (esValido)
{
// ...
}
2. Extrae condiciones complejas a variables
// Difícil de entender
if ((v >= 207 && v <= 253) && (i <= 16) && ((2*l*i*0.018)/s <= 6.9))
{
// ...
}
// Claro
bool voltajeOK = (voltaje >= 207 && voltaje <= 253);
bool corrienteOK = (corriente <= 16);
double caidaTension = (2 * longitud * corriente * 0.018) / seccion;
bool caidaOK = (caidaTension <= 6.9);
if (voltajeOK && corrienteOK && caidaOK)
{
// ...
}
3. Usa constantes para valores mágicos
// Mal: ¿qué significan estos números?
if (voltaje >= 207 && voltaje <= 253)
{
// ...
}
// Bien: significado claro
const double VOLTAJE_MINIMO = 207.0; // 230V - 10%
const double VOLTAJE_MAXIMO = 253.0; // 230V + 10%
if (voltaje >= VOLTAJE_MINIMO && voltaje <= VOLTAJE_MAXIMO)
{
// ...
}
Errores comunes
Error 1: Usar = en lugar de ==
int voltaje = 230;
if (voltaje = 400) // ERROR: asignación, no comparación
{
// ...
}
Solución:
if (voltaje == 400) // Comparación correcta
{
// ...
}
Error 2: Olvidar el break en switch
Lo veremos en detalle en el próximo capítulo, pero es un error muy común.
Error 3: Comparar strings con == sin considerar mayúsculas
string tipo = "motor";
if (tipo == "Motor") // No coincide
{
// No entra
}
Solución:
if (tipo.Equals("Motor", StringComparison.OrdinalIgnoreCase))
{
// Ahora sí coincide
}
Desafíos (Opcional)
Desafío 1: Clasificador de eficiencia energética
Dificultad: Bajo
Crea un script que clasifique motores según su eficiencia:
- IE4 (Super Premium): η ≥ 95%
- IE3 (Premium): 93% ≤ η < 95%
- IE2 (High Efficiency): 90% ≤ η < 93%
- IE1 (Standard): η < 90%
Muestra la clasificación y una recomendación.
Pista
Usa else if para cada rango de eficiencia, de mayor a menor.
Desafío 2: Selector de tipo de arranque para motores
Dificultad: Medio
Crea un script que seleccione el tipo de arranque según:
- Potencia del motor (kW)
- Tipo de carga (liviana, media, pesada)
- Limitación de corriente de arranque (sí/no)
Opciones: Directo, Estrella-Triángulo, Arrancador suave, Variador de frecuencia
Pista
Usa if anidados: primero verifica la potencia, luego el tipo de carga, finalmente la limitación de corriente.
Desafío 3: Calculadora de compensación reactiva completa
Dificultad: Alta
Crea un script que:
- Reciba: potencia activa, factor de potencia actual, voltaje
- Determine si necesita corrección (fp < 0.92)
- Si necesita: calcule el banco de capacitores (kVAr) para llegar a 0.95
- Seleccione el banco normalizado más cercano (5, 10, 15, 20, 25, 30, 40, 50 kVAr)
- Calcule el ahorro económico estimado (penalización evitada)
Pista
Usa if para verificar si necesita corrección, luego calcula el kVAr necesario, luego usa else if para seleccionar el banco normalizado.
Recursos adicionales
Preguntas frecuentes
P: ¿Cuándo usar else if y cuándo usar if separados?
R: Usa else if cuando las opciones son mutuamente excluyentes (solo una puede ser verdadera). Usa if separados cuando las condiciones son independientes y pueden ser verdaderas simultáneamente.
P: ¿El operador ternario es más eficiente que if/else?
R: No hay diferencia significativa de rendimiento. Usa ternario para asignaciones simples y legibles, usa if/else para lógica más compleja.
P: ¿Puedo poner un if dentro de un else?
R: Sí, pero generalmente es más claro usar else if en su lugar.
P: ¿Cuántos niveles de anidación son aceptables?
R: Como regla general, evita más de 2-3 niveles. Si necesitas más, considera refactorizar usando funciones o combinar condiciones con operadores lógicos.
P: ¿Importa el orden de las condiciones en else if?
R: Sí, mucho. Se evalúan en orden y se ejecuta el primer bloque verdadero. Pon las condiciones más específicas primero.
Checklist de completitud
Antes de pasar al siguiente capítulo, asegúrate de:
- Entender cómo funciona la estructura if básica
- Poder usar if/else para dos opciones
- Saber encadenar múltiples opciones con else if
- Comprender cuándo usar if anidados vs operadores lógicos
- Saber usar el operador ternario para asignaciones simples
- Poder comparar strings correctamente (sensible e insensible a mayúsculas)
- Haber ejecutado exitosamente el selector de protecciones
- Poder modificar los parámetros y ver cómo cambian las selecciones
- (Opcional) Haber intentado al menos un desafío
Última actualización: Enero 2025
Tiempo de lectura estimado: 45-55 minutos
Código de ejemplo: code/cap-05/