En esta página

Variables, tipos y operadores en C# 14

14 min lectura TextoCap. 1 — Fundamentos de C#

Tipos de datos en C#

C# es un lenguaje fuertemente tipado: toda variable tiene un tipo conocido en tiempo de compilación. El compilador rechaza operaciones incompatibles antes de ejecutar el programa, lo que elimina una categoría entera de errores.

Tipos de valor vs tipos de referencia

Esta es la distinción más importante en C#:

Categoría Tipos Almacenados en
Valor int, double, bool, char, decimal, struct Stack (pila)
Referencia string, class, array, object Heap (montículo)

Los tipos de valor se copian al asignarlos. Los tipos de referencia comparten la misma memoria:

// Tipo de valor — se copia
int a = 10;
int b = a;
b = 20;
Console.WriteLine(a); // 10 — no cambia

// Tipo de referencia — comparten referencia
int[] arr1 = { 1, 2, 3 };
int[] arr2 = arr1;
arr2[0] = 99;
Console.WriteLine(arr1[0]); // 99 — SÍ cambia

Tipos enteros

C# ofrece enteros de distintos tamaños para optimizar el uso de memoria:

byte  min = byte.MinValue;   // 0
byte  max = byte.MaxValue;   // 255
int   i   = int.MaxValue;    // 2,147,483,647
long  l   = long.MaxValue;   // 9,223,372,036,854,775,807

// BigInteger para números arbitrariamente grandes
using System.Numerics;
BigInteger enorme = BigInteger.Pow(10, 100); // 10^100

Usa int por defecto. Usa long si los valores pueden superar 2 mil millones. Usa byte solo cuando la memoria sea crítica.

Tipos de punto flotante

// Literales con sufijos obligatorios
float   precisionBaja  = 1.5f;     // sufijo 'f' obligatorio
double  precisionMedia = 1.5;      // por defecto es double
decimal precisionAlta  = 1.5m;     // sufijo 'm' obligatorio

// Valores especiales en double
double infinito = double.PositiveInfinity;
double nan      = double.NaN;
bool esNan      = double.IsNaN(nan); // true

// Constantes matemáticas
double pi = Math.PI;    // 3.141592653589793
double e  = Math.E;     // 2.718281828459045

Strings en C#

Los strings en C# son inmutables: cada operación crea un nuevo string. Para concatenación intensiva usa StringBuilder:

using System.Text;

// Strings normales
string nombre   = "David";
string apellido = "Morales";
string completo = nombre + " " + apellido; // concatenación (crea nuevo objeto)

// String interpolation — la forma preferida
string msg = $"Hola, {nombre}! Hoy es {DateTime.Now:dddd, dd MMMM yyyy}.";

// Verbatim strings — sin escapes
string ruta = @"C:\Users\David\Documentos\proyecto.cs";

// Raw string literals (C# 11+) — sin escapes, multilínea
string html = """
    <div class="card">
      <h1>Título</h1>
    </div>
    """;

// StringBuilder para concatenación masiva
var sb = new StringBuilder();
for (int i = 0; i < 1000; i++)
{
    sb.Append($"Línea {i}\n");
}
string resultado = sb.ToString();

Métodos esenciales de string:

string texto = "  Hola Mundo  ";
Console.WriteLine(texto.Trim());              // "Hola Mundo"
Console.WriteLine(texto.ToUpper());           // "  HOLA MUNDO  "
Console.WriteLine(texto.ToLower());           // "  hola mundo  "
Console.WriteLine(texto.Contains("Mundo"));   // true
Console.WriteLine(texto.Replace("Mundo", "C#")); // "  Hola C#  "
Console.WriteLine(texto.Split(' ').Length);   // divide en palabras

// Verificar si está vacío
string vacio = "";
Console.WriteLine(string.IsNullOrEmpty(vacio));       // true
Console.WriteLine(string.IsNullOrWhiteSpace("   "));  // true

const y readonly

// const — evaluado en tiempo de compilación
const double PI        = 3.14159265;
const int    MAX_ITEMS = 100;
const string APP_NAME  = "BemoreLearn";

// readonly — evaluado en tiempo de ejecución (dentro de clases)
class Config
{
    public readonly string ConnectionString;
    public readonly DateTime FechaInicio;

    public Config(string connStr)
    {
        ConnectionString = connStr;
        FechaInicio = DateTime.Now; // puede usar valores dinámicos
    }
}

Conversiones de tipos

// Conversión implícita (segura, no pierde datos)
int    entero = 42;
long   largo  = entero;   // int → long implícito
double doble  = entero;   // int → double implícito

// Conversión explícita (cast — puede perder datos)
double precio = 19.99;
int    enteroDesde = (int)precio;  // 19 — trunca decimales

// Parse — string a número (lanza excepción si falla)
int numero = int.Parse("42");
double d   = double.Parse("3.14");

// TryParse — versión segura (no lanza excepción)
if (int.TryParse("abc", out int resultado))
{
    Console.WriteLine($"Convertido: {resultado}");
}
else
{
    Console.WriteLine("Conversión fallida"); // este se ejecuta
}

// Convert — conversión general
string numStr = Convert.ToString(123);   // "123"
bool   boolVal = Convert.ToBoolean(1);   // true

Operadores

// ── Aritméticos ──────────────────────────────────────
int suma  = 10 + 3;   // 13
int resta = 10 - 3;   // 7
int multi = 10 * 3;   // 30
int div   = 10 / 3;   // 3 (división entera)
int mod   = 10 % 3;   // 1 (módulo/residuo)
double divReal = 10.0 / 3; // 3.333...

// Incremento/decremento
int x = 5;
Console.WriteLine(x++); // 5 (post-incremento: usa LUEGO incrementa)
Console.WriteLine(++x); // 7 (pre-incremento: incrementa LUEGO usa)

// ── Comparación ──────────────────────────────────────
bool ig  = (5 == 5);  // true
bool dif = (5 != 3);  // true
bool may = (5 > 3);   // true
bool men = (3 < 5);   // true
bool mig = (5 >= 5);  // true
bool mig2 = (3 <= 5); // true

// ── Lógicos ──────────────────────────────────────────
bool yAnd  = true && false; // false (AND)
bool oOr   = true || false; // true  (OR)
bool noNot = !true;         // false (NOT)

// ── Asignación compuesta ─────────────────────────────
int n = 10;
n += 5;  // n = 15
n -= 3;  // n = 12
n *= 2;  // n = 24
n /= 4;  // n = 6
n %= 4;  // n = 2

// ── Ternario ─────────────────────────────────────────
int edad = 20;
string acceso = edad >= 18 ? "Permitido" : "Denegado";

Práctica

  1. Tipos y conversiones: Crea un programa que pida al usuario dos números con Console.ReadLine(), conviértalos con double.TryParse, sume y muestre el resultado con formato {resultado:N2}.
  2. Nullable: Declara int? temperatura = null. Usa ?? para asignar 20 como valor por defecto si es null y muestra el resultado.
  3. StringBuilder: Genera una tabla de multiplicar del 1 al 10 usando StringBuilder y un bucle for.

En la siguiente lección veremos las estructuras de control de flujo (if/else, switch expressions, bucles) y la definición de métodos en C#.

Usa decimal para dinero
Nunca uses float ni double para representar valores monetarios. Los tipos float y double tienen errores de precisión de punto flotante (0.1 + 0.2 != 0.3). Siempre usa decimal para precios, saldos y cualquier cálculo financiero.
const vs readonly
const se evalúa en tiempo de compilación y solo acepta tipos primitivos. readonly se evalúa en tiempo de ejecución y puede asignarse en el constructor. Para constantes de clase usa const; para valores que dependen del entorno usa readonly.
Nullable reference types
Con <Nullable>enable en el .csproj, el compilador analiza si puedes acceder a una variable string sin verificar null. Aprovecha esta característica para eliminar NullReferenceException antes de tiempo de ejecución.
// ── Tipos enteros ────────────────────────────────────
byte  b  = 255;           // 0 a 255
sbyte sb = -128;          // -128 a 127
short s  = 32_767;        // guión bajo como separador visual
int   i  = 2_147_483_647;
long  l  = 9_223_372_036_854_775_807L;

// ── Tipos de punto flotante ──────────────────────────
float   f  = 3.14f;        // 7 dígitos de precisión
double  d  = 3.14159265;   // 15-17 dígitos de precisión
decimal m  = 19.99m;       // 28-29 dígitos — ideal para dinero

// ── Otros tipos primitivos ───────────────────────────
bool  activo  = true;
char  letra   = 'A';       // comillas simples para char
string nombre = "David";   // cadena de texto inmutable

// ── Inferencia con var ───────────────────────────────
var edad   = 30;           // int inferido
var precio = 99.99m;       // decimal inferido
var saludo = "Hola";       // string inferido

Console.WriteLine($"int máx: {int.MaxValue}");
Console.WriteLine($"decimal precisión: {decimal.MaxValue}");