Team LiB
Previous Section Next Section

Utility Classes

As we've just seen, static methods are used to provide generic functionality that is independent of any particular object. For example, we've been using the syntax

Console.WriteLine(string expression);

throughout the book to display messages to the console. As it turns out, Console is a class predefined in the .NET Framework Class Library (in the System name-space), and WriteLine is a static method on that class. We therefore needn't ever instantiate a Console object to print messages to the screen; we simply call the WriteLine method on the Console class as a whole.

Another example of a predefined class that is comprised wholly of static methods and public static attributes is the Math class (also in the System namespace).

We informally refer to such classes as utility classes.

User-Defined Utility Classes

We can use this same technique to create our own custom utility classes. For example, suppose that we were going to have a frequent need to do temperature conversions from degrees Fahrenheit to degrees Centigrade and vice versa. We could invent a utility class as follows:

// A utility class to provide F=>C and C=>F conversions.

public class Temperature {
  public static double FahrenheitToCentigrade(double tempF) {
    double tempC = (tempF - 32.0) * (5.0/9.0);
    return tempC;
  }

  public static double CentigradeToFahrenheit(double tempC) {
    double tempF = tempC * (9.0/5.0) + 32.0;
    return tempF;
  }
}

Then, to use this class, we'd simply write client code as follows:

double temp1 = 212.0;  // Boiling point on the Fahrenheit scale

// Calling our own static method.
double temp2 = Temperature.FahrenheitToCentigrade(temp);
Console.WriteLine("" + temp + " degrees F = " + temp2 + "degrees C");

This would give us the following output:

212.0 degrees F = 100.0 degrees C

We might even wish to include some commonly used constants—say, the boiling and freezing points of water in both F and C terms—as public static attributes in our utility class:


// A utility class to provide F=>C and C=>F conversions.

public class Temperature {
  // We've added some public static attributes.
  public static double FahrenheitFreezing = 32.0;
  public static double CentigradeFreezing = 0.0;
  public static double FahrenheitBoiling = 212.0;
  public static double CentigradeBoiling = 100.0;

  public static double FahrenheitToCentigrade(double tempF) {
    double tempC = (tempF – 32.0) * (5.0/9.0);
    return tempC;
  }

  public static double CentigradeToFahrenheit(double tempC) {
    double tempF = tempC * (9.0/5.0) + 32.0;
    return tempF;
  }
}

We could then take advantage of these constants in our client code, as well:

double soupTemperature;
// The value of soupTemperature is established ... details omitted.
if (soupTemperature >= Temperature.FahrenheitBoiling) { ... }

There is only one minor problem: we want these "constant" values to truly be constants, but as we've declared them previously—as public (static) attributes—there is nothing to prevent client code from altering their values:

Temperature.FahrenheitBoiling = 98.6;  // Whoops!

Fortunately, we can take advantage of a special type of variable known as a constant to remedy this problem.

Constants

A constant is a variable whose value can't be changed once it has been given an initial value. We declare a constant with the const keyword, as follows:

  public const double FahrenheitFreezing = 32.0;
  • Constants are implicitly static, and so the static keyword shouldn't be used in declaring them; if we try to do so:

          // The following line won't compile.
    
          public static const double FahrenheitFreezing = 32.0;
    

    the compiler will generate the following error:

          error CS0504: 'Temperature.FahrenheitFreezing' cannot be marked static
    
  • Constants must be given a value when they are declared; that is, we can't declare a const in one part of a program and assign it a value somewhere else. If we try to declare an uninitialized const:

          public const double FahrenheitFreezing;
    

    the compiler will generate the following error:

          error CS0145: a const field requires a value to be provided
    
  • The convention when naming constants is to use the Pascal capitalization style.

Let's retrofit our Temperature class with constant attributes:

// A utility class to provide F=>C and C=>F conversions.

public class Temperature
{
  // We've added the const keyword to these declarations.
  public const double FahrenheitFreezing = 32.0;
  public const double CentigradeFreezing = 0.0;
  public const double FahrenheitBoiling = 212.0;
  public const double CentigradeBoiling = 100.0;

  public static double FahrenheitToCentigrade(double tempF) {
    double tempC = (tempF - 32.0) * (5.0/9.0);
    return tempC;
  }
  public static double CentigradeToFahrenheit(double tempC) {
    double tempF = tempC * (9.0/5.0) + 32.0;
    return tempF;
  }
}

Now, if we attempt to alter the value of one of these truly constant constants from client code:

Temperature.FahrenheitBoiling = 98.6; // This won't compile!

we'd get the following (admittedly somewhat cryptic) compilation error:

error CS0219: The left-hand side of an assignment must be a variable,
property, or indexer

Of course, even within our Temperature class, this same prohibition exists: after the first assignment of a value to any const variable, that value is unchangeable.

Other facts about consts:

  • The initial value assigned to a const must be an expression that is computable at compile time:

                  public class MyUtilityClass
                {
                  // This will compile ...
                  public const int ImportantConstant = 123 + 456;
                  // This will NOT ...
                  public const double AnotherConstant = Math.Sqrt(2.0);
    

    In the preceding snippet, the second const declaration won't compile, because Math.Sqrt is a method and hence can only be invoked at run time.

  • The type of a const can only be one of the predefined numerical types (char, int, double, byte, etc.) or a string.

  • We may declare consts locally to a method, as well:

          public class SomeClass
          {
            // Details omitted.
            public void SomeMethod() {
              int x;
              const int y = 7;
              // etc.
            }
          }
    

Team LiB
Previous Section Next Section