2010-12-22 242 views
223

Por favor, explíqueme el uso del constructor estático. ¿Por qué y cuándo crearíamos un constructor estático y es posible sobrecargar uno?¿Para qué sirven los constructores estáticos?

+1

Cabe señalar que existen métodos estáticos de la construcción (por ejemplo, buscar el [patrón de diseño Singleton] (http://stackoverflow.com/questions/7095/is -the-c-sharp-static-constructor-thread-safe)) que se utilizan para ocultar los constructores reales utilizados para instanciar la clase. Esto le da al autor más control sobre cómo se usa su clase. – Izzy

Respuesta

186

No, no puede sobrecargar; un constructor estático es útil para inicializar cualquier campo estático asociado con un tipo (o cualquier otra operación por tipo), útil en particular para leer datos de configuración necesarios en campos de solo lectura, etc.

Se ejecuta automáticamente por el tiempo de ejecución primera vez es necesario (las reglas exactas son complicadas (vea "beforefieldinit"), y cambia sutilmente entre CLR2 y CLR4). A menos que abuse de la reflexión, se garantiza ejecutar como máximo una vez (incluso si llegan dos hilos al mismo tiempo).

+3

gracias por la respuesta. ¿Me puede dar más detalles sobre su oración? "A menos que abuse de la reflexión, se garantiza que se ejecutará como máximo una vez" ... ¿qué puede hacer con la reflexión sobre el constructor estático? –

+19

@Rajesh - encuentre el método y llame a 'Invoke' 20 veces. –

+0

Hola, @MarcGravell, aclara cuál es la diferencia entre el comportamiento de los constructores estáticos CLR2 y CLR4. Y también, ¿significa que los constructores estáticos son seguros para subprocesos? –

91

De Static Constructors (C# Programming Guide):

Un constructor estático se utiliza para inicializar cualquier datos estáticos, o para realizar una acción particular que necesite realiza sólo una vez. Se llama automáticamente antes de que se cree la primera instancia o se hace referencia a cualquier miembro estático.

constructores estáticos tienen las siguientes propiedades:

  • Un constructor estático no toma modificadores de acceso o tienen parámetros.

  • Un constructor estático se llama automáticamente para inicializar la clase antes de que se cree la primera instancia o se haga referencia a cualquier miembro estático.

  • No se puede llamar directamente a un constructor estático.

  • El usuario no tiene control sobre cuándo se ejecuta el constructor estático en el programa.

  • Un uso típico de constructores estáticos es cuando la clase está utilizando un archivo de registro y el constructor se utiliza para escribir entradas en este archivo.

  • Los constructores estáticos también son útiles al crear clases de contenedor para código no administrado, cuando el constructor puede llamar al método LoadLibrary.

7

puede usar el constructor estático para inicializar los campos estáticos. Se ejecuta en un tiempo indeterminado antes de que se usen esos campos. La documentación de Microsoft y muchos desarrolladores advierten que los constructores estáticos en un tipo imponen una sobrecarga sustancial.
Lo mejor es evitar los constructores estáticos para obtener el máximo rendimiento.
actualización: no puede utilizar más de un constructor estático en la misma clase, sin embargo, puede utilizar otros constructores de instancia con (máximo) un constructor estático.

+0

Puede ser excepcionalmente obvio, pero creo que esta respuesta llega a un punto clave implícito, por ejemplo, en la respuesta de marc: los constructores estáticos no son * en lugar de * constructores de instancias. Se les llama una vez, antes de que se cree la primera instancia, para configurar propiedades estáticas, etc. Los constructores de instancias siguen trabajando como siempre lo han hecho, configurando cosas particulares para esa instancia. static constructor': 'static class concerns' ::' instance constructor': 'inquietudes de nivel de instancia Tiene sentido. ; ^) – ruffin

8

1. Solo se puede acceder a los miembros estáticos de la clase.

Motivo: El miembro no estático es específico de la instancia del objeto. Si el constructor estático puede trabajar con miembros no estáticos, reflejará los cambios en toda la instancia del objeto, lo que no es práctico.

2.No debe haber parámetros en el constructor estático.

Motivo: Dado que CLR va a llamarlo, nadie puede pasarle el parámetro. 3. Solo se permite un constructor estático.

Motivo: La sobrecarga necesita que los dos métodos sean diferentes en términos de definición de método/constructor, lo cual no es posible en el constructor estático.

4.No debe haber ningún modificador de acceso a la misma.

Motivo: Otra vez la razón es la misma llamada al constructor estático se realiza por CLR y no por el objeto, sin necesidad de tener modificador de acceso a la misma

69

constructores estáticos son también muy útil cuando se tiene campos estáticos que se basan uno sobre el otro de tal manera que el orden de inicialización es importante. Si ejecuta su código a través de un formateador/embellecedor que cambia el orden de los campos, entonces puede encontrarse con valores nulos donde no los esperaba.

Ejemplo: Supongamos que tenemos esta clase:

class ScopeMonitor 
{ 
    static string urlFragment = "foo/bar"; 
    static string firstPart= "http://www.example.com/"; 
    static string fullUrl= firstPart + urlFragment; 
} 

Al acceder a fullUr, será "http://www.example.com/foo/bar".

Meses después, está limpiando su código y ordenando alfabéticamente los campos (digamos que son parte de una lista mucho más grande, para que no note el problema). Tiene:

class ScopeMonitor 
{ 
    static string firstPart= "http://www.example.com/"; 
    static string fullUrl= firstPart + urlFragment; 
    static string urlFragment = "foo/bar"; 
} 

Su valor fullUrl es ahora sólo "http://www.example.com/", ya que urlFragment no se había inicializado en el momento se estaba estableciendo fullUrl. No está bien. Así, se añade un constructor estático para cuidar de la inicialización:

class ScopeMonitor 
{ 
    static string firstPart= "http://www.example.com/"; 
    static string fullUrl; 
    static string urlFragment = "foo/bar"; 

    static ScopeMonitor() 
    { 
     fullUrl= firstPart + urlFragment; 

    } 
} 

Ahora, no importa el orden en que tiene los campos, la inicialización siempre será correcta.

+0

Si está utilizando ReSharper, creo que le avisará en esta situación cuando intente configurar fullUrl antes de que se haya inicializado urlFragment. Buen ejemplo, sin embargo. – Hardgraf

1

estático Constructor

Un constructor declara usando modificador static es un constructor estático. Un constructor estático se usa para inicializar datos estáticos o para realizar una acción particular que debe realizarse solo una vez en el ciclo de vida de la clase. El constructor estático es el primer bloque de código para ejecutar en clase. El constructor estático se ejecuta solo una vez en el ciclo de vida de la clase. Se llama automáticamente. El constructor estático no toma ningún parámetro. No tiene especificadores de acceso. No se llama directamente.

3

¿Por qué y cuándo crearíamos un constructor estático ...?

Una específica razón para utilizar un constructor estático es crear una clase 'super enumeración'.Aquí hay una (simple artificial,) ejemplo:

public class Animals 
{ 
    private readonly string _description; 
    private readonly string _speciesBinomialName; 

    public string Description { get { return _description; } } 
    public string SpeciesBinomialName { get { return _speciesBinomialName; } } 

    private Animals(string description, string speciesBinomialName) 
    { 
     _description = description; 
     _speciesBinomialName = speciesBinomialName; 
    } 

    private static readonly Animals _dog; 
    private static readonly Animals _cat; 
    private static readonly Animals _boaConstrictor; 

    public static Animals Dog { get { return _dog; } } 
    public static Animals Cat { get { return _cat; } } 
    public static Animals BoaConstrictor { get { return _boaConstrictor; } } 

    static Animals() 
    { 
     _dog = new Animals("Man's best friend", "Canis familiaris"); 
     _cat = new Animals("Small, typically furry, killer", "Felis catus"); 
     _boaConstrictor = new Animals("Large, heavy-bodied snake", "Boa constrictor"); 
    } 
} 

tendrá que utilizar muy similar (en el aspecto sintáctico) a cualquier otra enumeración:

Animals.Dog 

La ventaja de este sobre un habitual enum es que puede encapsular información relacionada fácilmente. Una desventaja es que no puede usar estos valores en una declaración switch (porque requiere valores constantes).

Cuestiones relacionadas