web-dev-qa-db-fra.com

Comment déclarer une instance de classe comme constante en C #?

Je dois implémenter ceci:

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

theTime est une constante (sérieusement :-), comme π est, dans mon cas, il serait inutile de le lire à partir des paramètres, par exemple. Et j'aimerais qu'il soit initialisé une fois et ne change jamais.

Mais C # ne semble pas permettre à une constante d'être initialisée par une fonction (qui est un constructeur). Comment surmonter cela?

39
Ivan

L'utilisation de readonly au lieu de const peut être initialisée et non modifiée par la suite. C'est ça que vous cherchez?

Exemple de code:

static class MyStaticClass
{
    public static readonly TimeSpan theTime;
    static MyStaticClass
    {
        theTime = new TimeSpan(13, 0, 0)
    }
}
60
ashelvey

Les constantes doivent être constantes dans le temps de compilation et le compilateur ne peut pas évaluer votre constructeur au moment de la compilation. Utilisez readonly et un constructeur static .

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 général, je préfère initialiser dans le constructeur plutôt que par affectation directe car vous contrôlez l'ordre d'initialisation.

39
James Gaunt

const de C # n'a pas la même signification que const de C++. En C #, const est utilisé pour définir essentiellement les alias des littéraux (et ne peut donc être initialisé qu'avec des littéraux). readonly est plus proche de ce que vous voulez, mais gardez à l'esprit qu'il n'affecte que l'opérateur d'affectation (l'objet n'est pas vraiment constant à moins que sa classe n'ait une sémantique immuable).

11

De ce lien :

Les constantes doivent être un type de valeur (sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal ou bool), une énumération, un littéral de chaîne ou une référence à null.

Si vous souhaitez créer un objet, vous devez le faire comme 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;
  }
}
7
John Leehey
public static readonly TimeSpan theTime = new TimeSpan(13, 0, 0);
4
lance

La constante représente un membre statique dont la valeur ne peut jamais changer. Cela signifie qu'une valeur constante est définie au moment de la compilation.
Avec la déclaration:

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

Sont violés deux axiomes de champs constants:

  • Seuls les types intégrés C # (à l'exception de System.Object) peuvent être déclarés const.
  • La valeur d'iniatialisation doit être évaluée au moment de la compilation

Dans la question est utilisé le type TimeSpan, qui n'est pas intégré (prédéfini) Type. Cela signifie que le compilateur csc.exe ne peut pas le reconnaître.
Si vous utilisez un type C # intégré (par exemple, String) et que vous souhaitez initialiser le membre constant avec une valeur de temps de compilation, vous obtenez toujours une erreur: par exemple.

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

Pour résoudre le problème, vous pouvez déclarer un membre avec:

static readonly

modificateur si vous souhaitez déclarer un champ une seule fois lors de l'exécution:

public static readonly string MyNumber = SetMyString();
private static string SetMyString()
{
 return "test";
}
1
George Kargakis

Vous pouvez utiliser le mot clé en lecture seule:

Lorsqu'une déclaration de champ inclut un modificateur en lecture seule, les affectations aux champs introduits par la déclaration ne peuvent se produire que dans le cadre de la déclaration ou dans un constructeur de la même classe.

Exemple (copié à partir de la page MSDN liée):

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