2011-06-03 19 views
29

necesito para implementar esta:¿Cómo declarar una instancia de clase como una constante en C#?


static class MyStaticClass 
{ 
    public const TimeSpan theTime = new TimeSpan(13, 0, 0); 
    public static bool IsTooLate(DateTime dt) 
    { 
    return dt.TimeOfDay >= theTime; 
    } 
} 

thetime es una constante (en serio :-), al igual que π es, en mi caso sería inútil leerlo de configuración, por ejemplo). Y me gustaría que se inicialice una vez y nunca cambie. Pero C# no parece permitir que una constante sea inicializada por una función (que es un constructor). ¿Cómo superar esto?

Respuesta

48

Uso readonly en lugar de const se puede inicializar y sin modificar después de eso. ¿Es eso lo que estás buscando?

+6

Downvoters: explique por qué está bajando una respuesta que resolvió la pregunta del OP. Si no es una buena solución, al menos explica por qué. – ashelvey

+0

porque ser objetivo es muy difícil;) –

+3

Utilizo esto en mi propio código, pero mi personalidad anal retentiva sabe que cada vez que hago esto, hay un objeto viviente largo en memoria de mi aplicación. Tengo una aplicación de larga ejecución que ya usa demasiada memoria y me molesta. Ojalá hubiera un TimeSpan literal que se compilara en mi código. La alternativa es tener un const int, convirtiendo mi valor TimeSpan a milisegundos ... pero matemática. – Dude0001

34

Las constantes deben compilarse como constantes de tiempo, y el compilador no puede evaluar su constructor en tiempo de compilación. Use readonly y static constructor.

static class MyStaticClass 
{ 
    static MyStaticClass() 
    { 
    theTime = new TimeSpan(13, 0, 0); 
    } 

    public static readonly TimeSpan theTime; 
    public static bool IsTooLate(DateTime dt) 
    { 
    return dt.TimeOfDay >= theTime; 
    } 
} 

En general prefiero para inicializar en el constructor y no por asignación directa y cuando usted tiene el control sobre el orden de inicialización.

+0

'theTime' debería haber 'static' también. Para que solo haya uno, y para que compile el ejemplo anterior. – pickypg

+4

¿Por qué un constructor? Simplemente describiendo un miembro como público estático de solo lectura TimeSpan theTime = new TimeSpan (13, 0, 0) parece funcionar (no hay errores de compilación al menos). – Ivan

+5

@pickypg - lo siento mi error - corregido. @Ivan - Agregué un comentario sobre eso. Personalmente, no me gusta la inicialización directa, ya que necesita buscar en una clase para descubrir dónde se inicializan las cosas. La inicialización siempre en el constructor es consistente y se puede ver fácilmente cuál es el estado inicial de una clase. También tiene control directo sobre el orden en que se lleva a cabo la inicialización. En un caso trivial de clase estática probablemente no haya mucha diferencia. Pero la buena práctica es una buena práctica, especialmente en los casos límite. –

4
public static readonly TimeSpan theTime = new TimeSpan(13, 0, 0); 
7

De this link:

Constants must be a value type (sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, or bool), an enumeration, a string literal, or a reference to null.

Si desea crear un objeto, hay que hacerlo de manera que static readonly:

static class MyStaticClass 
{ 
    public static readonly TimeSpan theTime = new TimeSpan(13, 0, 0); 
    public static bool IsTooLate(DateTime dt) 
    { 
    return dt.TimeOfDay >= theTime; 
    } 
} 
9

C# 's const no tiene el mismo significado que C++' s const. En C#, const se utiliza para definir esencialmente alias a literales (y, por lo tanto, solo se puede inicializar con literales). readonly está más cerca de lo que desea, pero tenga en cuenta que solo afecta al operador de asignación (el objeto no es realmente constante a menos que su clase tenga semántica inmutable).

+3

Vale la pena mencionar aquí que los campos 'de lectura estática' ** pueden ** cambiarse a través de la reflexión, mientras que' const' **no poder**. – GDS

0

Usted puede utilizar la palabra clave de sólo lectura:

When a field declaration includes a readonly modifier, assignments to the fields introduced by the declaration can only occur as part of the declaration or in a constructor in the same class.

Ejemplo (copiado de la página vinculada MSDN):

class Age 
{ 
    readonly int _year; 
    Age(int year) 
    { 
     _year = year; 
    } 
    void ChangeYear() 
    { 
     //_year = 1967; // Compile error if uncommented. 
    } 
} 
1

constante representa un miembro estático cuyo valor no puede cambiar nunca. Esto significa que un valor constante se define en tiempo de compilación.
con la declaración:

public const TimeSpan theTime = new TimeSpan(13, 0, 0); 

se violan los dos axiomas de campos constantes:

  • Sólo el C# tipos integrados (excluyendo System.Object) podrá ser declarada como const.
  • valor Iniatialization debe evaluarse en tiempo de compilación

En la pregunta se utiliza el tipo TimeSpan, que no es incorporado (predefinido) Tipo. Esto significa que el compilador csc.exe no puede reconocerlo.
Si usa un tipo de C# incorporado (por ejemplo, String) y desea inicializar el miembro constante con un valor de tiempo de compilación, sigue apareciendo un error: p.

public const string MyNumber = SetMyString(); 
private string SetMyString() 
{ 
    return "test"; 
} 

La solución del problema se puede declarar un miembro con:

static readonly 

modificador si desea declarar un campo de una sola vez en tiempo de ejecución:

public static readonly string MyNumber = SetMyString(); 
private static string SetMyString() 
{ 
return "test"; 
} 
Cuestiones relacionadas