This is your first visit inside The Matrix. Welcome!

The Matrix has you…

This place will take you into the mirage of learning C# programming language, without any previous coding experience being required

Follow the White Rabbit…█

Close
Friday, November 24, 2017 16:32

Constants

Just like constants in mathematics, C# defines special fields of classes called constants. Like their name hints, once declared and initialized, constants maintain their values, forbidding their further modification.

There are two types of constants:

  • constants for which the value is set during the compilation (compile time constants)
  • constants which have their value set during the execution (run-time constants)

Compile time constants are declared using the C# modifier const:

[<access_modifiers>] const <type> <name>;

A secret not many C# programmers know is that compile time constants are static fields, even if they do not contain the static keyword, and the compiler forbids its usage in the declaration.

As an example, the most known and simple constant we can declare is the math Pi number (or, better said, part of it):

public const double PI = 3.141592653589;

As you can see, we declared a double constant by specifying an access modifier, followed by the const modifier, the type of the variable, and its name.

A constant can also be any sort of expression that can be evaluated at compilation time. For instance:

public const double PI = 22d / 7;

since, as we know from math classes, Pi can be represented as the approximate division of numbers 22 and 7. So:

public const double PI = 22d / 7;

static void Main()
{
    Console.WriteLine("The value of PI is: " + PI);
    Console.Read();
}

will display

constants

Since constants are… well, constant, we cannot modify/assign them in any other place or moment except the declaration. This code:

public const double PI;

public void SetPiValue()
{
    // Attempting to initialize the constant PI
    PI = 3.141592653589793;
}

will generate the following compiler error: A const field requires a value to be provided.

There is another danger that some of you more adventurous programmers may encounter. Lets take an example to illustrate this.

Lets consider we want to create a Color class using the RGB (red-green-blue) model, which specifies that any color is a combination of different values of red, green and blue, specified as integers from 0 to 255. For instance, black is represented as (0, 0, 0), white as (255, 255, 255), blue as (0, 0, 255), etc.

So, we create our Color object by defining 3 private fields, and a constructor for initializing them:

class Color
{
    private int red;
    private int green;
    private int blue;

    public Color(int red, int green, int blue)
    {
        this.red = red;
        this.green = green;
        this.blue = blue;
    }
}

Now, let’s consider that some colors are used more frequently, for instance black and white (yeah, I know neither of them are colors, but for the sake of the lesson…). So, it would be really helpful if we would offer the users some constants holding those colors values, so they don’t have to specify them each time:

class Color
{
    public const Color BLACK = new Color(0, 0, 0);
    public const Color WHITE = new Color(255, 255, 255); 

    private int red;
    private int green;
    private int blue;

    public Color(int red, int green, int blue)
    {
        this.red = red;
        this.green = green;
        this.blue = blue;
    }
}

Everything seems OK to you? Well, strangely, it is not: ‘Color.BLACK’ is of type ‘Color’. A const field of a reference type other than string can only be initialized with null. The reason for this compiler error is because constants declared with the word const can only be of following types:

  1. Primitive types: sbyte, byte, short, ushort, int, uint, long, ulong, char,  float, double, decimal, bool.
  2. Enumerated types (we will learn about enumerations in the future).
  3. Reference types (mostly the type string).

The problem with the compilation of the class in our example is connected with the reference types and the restriction on the compiler not to allow simultaneous use of the operator new when declaring a constant when this constant is declared with the modifier const, unless the reference type can be calculated at compile time.

As we can guess, the only reference type, which can be calculated at compile time while using the operator new is string. Therefore, the only possibilities for reference type constants that are declared with modifier const are as follows:

  • The constants must be of type string.
  • The value which we assign to the constant of reference type, other than string, is null.

So, we learned that using the modifier const we will not be able to declare the constants Black and White of type Color in our color class because they aren’t null. In the next section I will show you how to deal with this problem.

Run time constants come in handy when we have to declare reference type constants, which cannot be calculated during the compilation. They are declared like this:

[<access_modifiers>] static readonly <reference_type> <name>;

This implies that <reference_type> is a type of which value is no known at compile time. So, correcting the above piece of code:

class Color
{
    public static readonly Color BLACK = new Color(0, 0, 0);
    public static readonly Color WHITE = new Color(255, 255, 255); 

    private int red;
    private int green;
    private int blue;

    public Color(int red, int green, int blue)
    {
        this.red = red;
        this.green = green;
        this.blue = blue;
    }
}

will make our program compile and run without any problems.

You may ask yourself, what is the real use of a value we cannot change? Well, constants are used in programming to avoid repetition of numbers, strings or other common values (literals) in the program and to enable them to change easily. The use of constants instead of brutally hardcoded repeating values facilitates readability and maintenance of the code and is highly recommended practice. According to some authors all literals other than 0, 1, -1, empty string, true, false and null must be declared as constants, but I am rather skeptical, as this can make it difficult to read and maintain the code instead of making it simple. Therefore, it is believed that values which occur more than once in the program or are likely to change over time, must be declared as constants.

You may have noticed that I named the constants using all caps letters. Perhaps it would be a good time for you to re-read the lesson “Choosing significant variable names” which explained it in more detail.

Comments

comments

Tags: , ,

Leave a Reply