Menu

static en C#: clases, métodos, campos y constructores static

Qué significa static en C#: miembros que pertenecen al tipo en lugar de a un objeto, estado compartido entre instancias, métodos static y clases static, constructores static, const frente a static readonly, using static y el error CS0120.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

static marca un miembro que pertenece al tipo, no a un objeto. Un campo de instancia existe una vez por objeto; un campo static existe una vez y punto. Un método de instancia se ejecuta sobre un objeto (order.Ship()); un método static se ejecuta sobre el tipo (Math.Round(x)) y no necesita ningún objeto.

Campos static: una copia, compartida

La forma más clara de ver la diferencia es un contador. Cada Order tiene su propio Id, pero el número de pedidos creados hasta el momento tiene que vivir en algún sitio compartido.

Salida:

Ana #1, Ben #2, Chen #3
Orders created: 3

A los miembros static se accede a través del nombre del tipo: Order.Created, no a.Created. C# no permite llegar a un miembro static a través de una instancia (error CS0176), lo que deja claro en el punto de llamada que el valor es compartido.

Métodos static

Un método static no tiene this. Solo trabaja con sus parámetros y con otros miembros static. Eso lo convierte en la forma natural de los métodos auxiliares que calculan algo a partir de sus entradas:

Salida:

61.38 EUR
7

El propio Main es static: el runtime lo llama antes de que exista ningún objeto.

El error CS0120: código static que usa miembros de instancia

Como Main es static, los principiantes suelen encontrarse este error en cuanto añaden un segundo método:

class Program
{
    int visits;
    void Greet() { Console.WriteLine("Hello"); }

    static void Main()
    {
        Greet();    // error CS0120: An object reference is required for the non-static field, method, or property 'Program.Greet()'
        visits++;   // error CS0120: An object reference is required for the non-static field, method, or property 'Program.visits'
    }
}

Un método static no tiene objeto, así que no hay ningún visits que incrementar. Hay dos soluciones, y la correcta depende de lo que sea el miembro:

  • El miembro es de verdad un dato de cada objeto: crea un objeto y úsalo. var app = new Program(); app.Greet();
  • El miembro no necesita estado de objeto: márcalo como static. static void Greet() { ... }

Marcar todo como static para que desaparezca el error funciona en un programa diminuto y se convierte en estado global en uno real. Decide preguntándote si el dato pertenece a un objeto o a todo el programa.

La dirección contraria siempre está permitida: los métodos de instancia pueden llamar libremente a los miembros static.

Clases static

Una clase declarada static solo puede contener miembros static y nunca puede instanciarse. Es un grupo con nombre de funciones y constantes.

Salida:

77
100
True

El compilador hace cumplir el contrato: un miembro de instancia dentro de una clase static es el error CS0708, y new sobre ella es el error CS0712. Math, Console, File, Path y Enumerable son todas clases static. Los métodos de extensión también deben vivir en una clase static.

Constructores static y static readonly

Un campo static cuyo valor necesita más de una expresión puede asignarse en un constructor static, que el runtime ejecuta una vez, antes de que el tipo se use por primera vez:

Salida:

Before first use
ShippingRates initialized
5.50
3
2026-01-01

readonly significa que el campo solo puede asignarse en su inicializador o en el constructor static. Después no puede reasignarse, aunque el objeto al que apunta aún podría ser mutable, y por eso el diccionario se expone como IReadOnlyDictionary.

const frente a static readonly

Los dos te dan un valor con nombre compartido por todo el programa, y se diferencian en cuándo se fija el valor:

conststatic readonly
El valor se fija entiempo de compilacióntiempo de ejecución, una vez
Tipos permitidosnúmeros, char, bool, string, enums, nullcualquier tipo
Implícitamente staticsí (no se puede escribir static const)se declara static de forma explícita
Se copia en los ensamblados que lo usansíno, se lee del campo
Se puede usar en cases de switch y argumentos de atributossíno

La fila de la copia importa en las bibliotecas: si el ensamblado A declara public const int MaxItems = 50; y el ensamblado B lo usa, B contiene el literal 50. Cambiar A a 100 no hace nada en B hasta que B se recompila. Para valores que pueden cambiar entre versiones, prefiere static readonly.

using static

Una directiva using static (C# 6) importa los miembros static de un tipo, para que puedas llamarlos sin el nombre del tipo:

Salida:

Area: 28.27
40

Se lee bien en código con muchas matemáticas. En otros casos, úsala con moderación: un WriteLine o un Parse sueltos ocultan de qué tipo viene el método.

Estado static e hilos

Un campo static lo comparten todos los hilos del proceso. Incrementarlo desde varios hilos a la vez pierde actualizaciones, porque created++ es una lectura, una suma y una escritura, y dos hilos pueden intercalarlas. Usa Interlocked.Increment(ref created) para los contadores, o un lock para cualquier cosa más grande. Las aplicaciones web son el sitio habitual donde esto muerde: cada petición se ejecuta en algún hilo, así que un campo static que guarde "el usuario actual" lo comparten todos los usuarios.

Un detalle más: en una clase genérica, cada tipo construido tiene sus propios campos static. Cache<int>.Count y Cache<string>.Count son dos campos distintos.

Cuándo usar static

Buenos usos:

  • Métodos auxiliares puros que calculan un resultado a partir de sus argumentos: formato, conversiones, validación.
  • Constantes y datos de consulta de solo lectura compartidos por el programa.
  • Métodos de fábrica, como TimeSpan.FromMinutes(5) o tu propio Temperature.FromCelsius(21).
  • Métodos de extensión.

Malos usos:

  • Estado global mutable (el usuario actual, un carrito de la compra, una configuración que cambia). Acopla todo el código que lo toca y hace que las pruebas dependan de lo que dejaron las demás.
  • Todo lo que vayas a querer sustituir en las pruebas, como un reloj, una base de datos o un servicio de envío de correo. Las llamadas static no pueden sustituirse por una falsa; una instancia pasada al constructor sí.

Preguntas frecuentes

¿Qué significa static en C#?

Un miembro static pertenece al propio tipo y no a ningún objeto. Hay una sola copia de un campo static, existan los objetos que existan, y un método static se llama sobre el nombre del tipo (Math.Max(3, 7)) sin crear ninguna instancia. Un método static no tiene this, así que no puede usar directamente los campos de instancia.

¿Qué es una clase static en C#?

Una clase declarada static solo puede contener miembros static y nunca puede instanciarse (new sobre ella es el error CS0712). Agrupa funciones relacionadas que no necesitan estado de objeto, como Math, Console o File. Los métodos de extensión deben declararse en una clase static.

¿Cómo arreglo "An object reference is required for the non-static field, method, or property"?

Es el error CS0120: un método static, a menudo Main, está usando un miembro de instancia. O bien crea un objeto y llama al miembro sobre él (var app = new Program(); app.Run();), o bien marca el miembro como static si no necesita datos de cada objeto.

¿Qué diferencia hay entre const y static readonly en C#?

Un const es una constante de tiempo de compilación (números, strings, bool, enums) cuyo valor se copia en todos los ensamblados que la usan. Un campo static readonly se asigna una vez en tiempo de ejecución, en su inicializador o en el constructor static, y puede ser de cualquier tipo, como un DateTime o una lista. Usa const para los valores que nunca cambiarán y static readonly para todo lo demás.

¿Cuándo debo usar static en C#?

Usa static para el código que solo trabaja con sus parámetros (métodos auxiliares puros, como un formateador de precios), para constantes y cachés que de verdad son globales al programa, y para los métodos de fábrica. Evita static para todo lo que guarde estado por usuario o por petición, o que vayas a querer sustituir en las pruebas: el estado mutable compartido es difícil de probar y no es seguro entre hilos sin bloqueos.

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR