简体   繁体   中英

How to declare a class instance as a constant in C#?

I need to implement this:

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

theTime is a constant (seriously:-), like π is, in my case it'd be pointless to read it from settings, for example. And I'd like it to be initialized once and never changed.

But C# doesn't seem to allow a constant to be initialized by a function (which a constructor is). How to overcome this?

Using readonly instead of const can be initialized and not modified after that. Is that what you're looking for?

Code example:

static class MyStaticClass
{
    static readonly TimeSpan theTime;

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

Constants have to be compile time constant, and the compiler can't evaluate your constructor at compile time. Use readonly and a 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;
  }
}

In general I prefer to initialise in the constructor rather than by direct assignment as you have control over the order of initialisation.

C#'s const does not have the same meaning as C++'s const . In C#, const is used to essentially define aliases to literals (and can therefore only be initialized with literals). readonly is closer to what you want, but keep in mind that it only affects the assignment operator (the object isn't really constant unless its class has immutable semantics).

From 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.

If you want to create an object, it must be done so as 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;
  }
}
public static readonly TimeSpan theTime = new TimeSpan(13, 0, 0);

You can use the readonly keyword :

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.

Example (copied from the linked MSDN page):

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

Constant represents a static member whose value can never change. This means that a constant value is defined in compile time.
With the statement:

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

Are violated two axioms of constant fields:

  • Only the C# built-in types (excluding System.Object) may be declared as const.
  • Iniatialization value must be evaluated in compile time

In the question is used the TimeSpan type, which is not built-in (predefined) Type. This means that the csc.exe compiler cannot recognize it.
If you use a built-in C# type (eg String) and you want to initialize the constant member with a compile time value, you still get an error: eg

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

Solving the problem you can declare a member with:

static readonly

modifier if you want to declare a field only once in runtime:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM