Clases estáticas y sus miembros (Guía de programación de C#)

Una clase estática es básicamente igual que una clase no estática, pero existe una diferencia: no se pueden crear instancias de una clase estática. En otras palabras, no puede utilizar la palabra clave new para crear una variable del tipo clase. Dado que no hay ninguna variable de instancia, el acceso a los miembros de una clase estática se realiza mediante el propio nombre de clase. Por ejemplo, si cuenta con una clase estática que se denomina UtilityClass e incluye un método público denominado MethodA, la llamada al método se realiza tal como se muestra en el ejemplo siguiente:

UtilityClass.MethodA();

Una clase estática se puede utilizar como un contenedor adecuado para los conjuntos de métodos que solo funcionan en parámetros de entrada y no tienen que obtener ni establecer campos internos de instancia. Por ejemplo, en la biblioteca de clases .NET Framework, la clase estática System.Math contiene varios métodos que realizan operaciones matemáticas, sin ningún requisito para almacenar o recuperar datos únicos de una instancia determinada de la clase Math. Es decir, los miembros de la clase se aplican especificando el nombre de la clase y del método, como se muestra en el ejemplo siguiente.

double dub = -3.14;
Console.WriteLine(Math.Abs(dub));
Console.WriteLine(Math.Floor(dub));
Console.WriteLine(Math.Round(Math.Abs(dub)));

// Output:
// 3.14
// -4
// 3

Como sucede con todos los tipos de clase, Common Language Runtime (CLR) de .NET Framework carga la información de tipo de una clase estática cuando se carga el programa que hace referencia a la clase. El programa no puede especificar exactamente cuándo se carga la clase. Sin embargo, se garantiza que se ha cargado, que sus campos se han inicializado y que se ha llamado a su constructor estático antes de que se haga referencia a la clase por primera vez en el programa. Solo se llama una vez a un constructor estático y una clase estática permanece en memoria durante el período de duración del dominio de aplicación donde reside el programa.

Nota

Para crear una clase no estática que permita crear solo una instancia de sí misma, vea Implementing Singleton in C#.

En la siguiente lista se proporcionan las características principales de una clase estática:

  • Solo contiene miembros estáticos.

  • No se pueden crear instancias de ella.

  • Es de tipo sealed.

  • No puede contener constructores de instancia.

Crear una clase estática es, por consiguiente, básicamente igual que crear una clase que solo contiene miembros estáticos y un constructor privado. Un constructor privado evita que se creen instancias de la clase. La ventaja de utilizar una clase estática es que el compilador puede comprobar que no se agregue accidentalmente ningún miembro de instancia. El compilador garantizará que no se puedan crear instancias de esta clase.

Las clases estáticas son de tipo sealed y, por consiguiente, no pueden heredarse. No pueden heredar de cualquier clase, excepto Object. Las clases estáticas no pueden contener un constructor de instancia; sin embargo, pueden contener un constructor estático. Las clases no estáticas también deben definir un constructor estático si contienen miembros estáticos que requieren una inicialización no trivial. Para obtener más información, vea Constructores estáticos (Guía de programación de C#).

Ejemplo

Este es un ejemplo de clase estática que contiene dos métodos que convierten la temperatura de grados Celsius a Fahrenheit y viceversa:

    public static class TemperatureConverter
    {
        public static double CelsiusToFahrenheit(string temperatureCelsius)
        {
            // Convert argument to double for calculations.
            double celsius = Double.Parse(temperatureCelsius);

            // Convert Celsius to Fahrenheit.
            double fahrenheit = (celsius * 9 / 5) + 32;

            return fahrenheit;
        }

        public static double FahrenheitToCelsius(string temperatureFahrenheit)
        {
            // Convert argument to double for calculations.
            double fahrenheit = Double.Parse(temperatureFahrenheit);

            // Convert Fahrenheit to Celsius.
            double celsius = (fahrenheit - 32) * 5 / 9;

            return celsius;
        }
    }

    class TestTemperatureConverter
    {
        static void Main()
        {
            Console.WriteLine("Please select the convertor direction");
            Console.WriteLine("1. From Celsius to Fahrenheit.");
            Console.WriteLine("2. From Fahrenheit to Celsius.");
            Console.Write(":");

            string selection = Console.ReadLine();
            double F, C = 0;

            switch (selection)
            {
                case "1":
                    Console.Write("Please enter the Celsius temperature: ");
                    F = TemperatureConverter.CelsiusToFahrenheit(Console.ReadLine());
                    Console.WriteLine("Temperature in Fahrenheit: {0:F2}", F);
                    break;

                case "2":
                    Console.Write("Please enter the Fahrenheit temperature: ");
                    C = TemperatureConverter.FahrenheitToCelsius(Console.ReadLine());
                    Console.WriteLine("Temperature in Celsius: {0:F2}", C);
                    break;

                default:
                    Console.WriteLine("Please select a convertor.");
                    break;
            }

            // Keep the console window open in debug mode.
            Console.WriteLine("Press any key to exit.");
            Console.ReadKey();
        }
    }
    /* Example Output:
        Please select the convertor direction
        1. From Celsius to Fahrenheit.
        2. From Fahrenheit to Celsius.
        :2
        Please enter the Fahrenheit temperature: 20
        Temperature in Celsius: -6.67
        Press any key to exit.
     */

Miembros estáticos

Una clase no estática puede contener métodos, campos, propiedades o eventos estáticos. El miembro estático es invocable en una clase incluso si no se ha creado ninguna instancia de la clase. El nombre de clase, y no el nombre de instancia, es el que tiene acceso al miembro estático. Solo existe una copia de un miembro estático, independientemente del número de instancias que se creen de la clase. Los métodos y propiedades estáticos no pueden tener acceso a los campos y eventos no estáticos de su tipo contenedor y no pueden tener acceso a una variable de instancia de ningún objeto a menos que se pase explícitamente en un parámetro de método.

Es más habitual declarar una clase no estática con algunos miembros estáticos que declarar toda una clase como estática. Dos usos comunes de los campos estáticos son mantener un recuento del número de objetos de los que se han creado instancias y almacenar un valor que se debe compartir entre todas las instancias.

Los métodos estáticos se pueden sobrecargar pero no invalidar, porque pertenecen a la clase y no a una instancia de la clase.

Aunque un campo no se puede declarar como static const, un campo const es esencialmente estático en su comportamiento. Pertenece al tipo, no a las instancias del tipo. Por tanto, se puede tener acceso a los campos de constante mediante la misma notación ClassName.MemberName que se utiliza para los campos estáticos. No se requiere ninguna instancia de objeto.

C# no admite las variables local estáticas (variables que se declaran en el ámbito del método).

Los miembros estáticos de la clase se declaran mediante la incorporación de la palabra clave static antes del tipo de valor devuelto del miembro, tal como se muestra en el ejemplo siguiente:

public class Automobile
{
    public static int NumberOfWheels = 4;
    public static int SizeOfGasTank
    {
        get
        {
            return 15;
        }
    }
    public static void Drive() { }
    public static event EventType RunOutOfGas;

    // Other non-static fields and properties...
}

Los miembros estáticos se inicializan antes de obtener acceso al miembro estático por primera vez y antes de llamar al constructor estático, si éste existe. Para tener acceso a un miembro estático de la clase, utilice el nombre de la clase en lugar de un nombre de variable para especificar la ubicación del miembro, tal como se muestra en el siguiente ejemplo:

Automobile.Drive();
int i = Automobile.NumberOfWheels;

Si la clase contiene campos estáticos, proporcione un constructor estático que los inicialice cuando se cargue la clase.

Una llamada a un método estático genera una instrucción de llamada en el lenguaje intermedio de Microsoft (MSIL), mientras que una llamada a un método de instancia genera una instrucción callvirt, que también comprueba las referencias de objeto nulas. Sin embargo, la mayoría de las veces la diferencia de rendimiento entre ambas no es significativa.

Especificación del lenguaje C#

Para obtener más información, vea la Especificación del lenguaje C#. La especificación del lenguaje es la fuente definitiva de la sintaxis y el uso de C#.

Vea también

Referencia

static (Referencia de C#)

Clases (Guía de programación de C#)

class (Referencia de C#)

Constructores estáticos (Guía de programación de C#)

Constructores de instancias (Guía de programación de C#)

Conceptos

Guía de programación de C#

Diseño de clases estáticas