A Null Object

Introduction

We already know that, to create an object, you can declare a variable of its class. Here is an example:

Microwave machine;

public class MicrowaveOven
{
}

Once you have a class, you can pass it to a function and use it, such as displaying its values to a user. Here is an example:

using static System.Console;

void Present(MicrowaveOven mw)
{
    Write("Make: ");
    Write(mw.Make);
}

MicrowaveOven machine;

public class MicrowaveOven
{
    public string Make { get; set; }
}

Practical LearningPractical Learning: Introducing Nullity

  1. Start Microsoft Visual Studio and create a C# Console App that supports the .NET 7.0 (Standard Term Support).
    Name the project as Chemistry6
  2. On the main menu, click Project -> Add Class...
  3. Change the file name to Element
  4. Click Add
  5. Change the document and class as follows:
    namespace Chemistry6
    {
        public enum Phase { Gas, Liquid, Solid, Unknown }
    
        internal class Element
        {
            internal string ElementName  { get; set; }
            internal string Symbol       { get; set; }
            internal int    AtomicNumber { get; set; }
            internal double AtomicWeight { get; set; }
            internal Phase  Phase        { get; set; }
    
            public Element()                 { }
            public Element(string symbol) => Symbol = symbol;
            public Element(int number)    => AtomicNumber = number;
    
            public Element(int number, string symbol, string name, double mass, Phase phase)
            {
                ElementName  = name;
                AtomicWeight = mass;
                Phase        = phase;
                Symbol       = symbol;
                AtomicNumber = number;
            }
        }
    }
  6. In the Solution Explorer, right-click Program.cs and click Rename
  7. Type PeriodicTable (to get PeriodicTable.cs) and press enter
  8. Click the PeriodicTable.cs tab and change the document as follows:
    using Chemistry6;
    using static System.Console;
    
    void Present(Element obj)
    {
        WriteLine("Chemistry");
        WriteLine("--------------------------");
        WriteLine("Symbol:        " + obj.Symbol);
        WriteLine($"Atomic Number: {obj.AtomicNumber}");
        WriteLine("Element Name:  " + obj.ElementName);
        WriteLine($"Atomic Weight: " + obj.AtomicWeight);
        WriteLine("Phase/State:   " + obj.Phase);
        Write("==========================");
    }
    
    Element Prepare()
    {
        Element h = new(1, "H", "Hydrogen", 1.008, Phase.Gas);
        Element he = new(2, "He", "Helium", 4.002602, Phase.Gas);
        Element li = new(3, "Li", "Lithium", 6.94, Phase.Solid);
        Element be = new(4, "Be", "Beryllium", 9.0121831, Phase.Solid);
        Element b = new(5, "B", "Boron", 10.81, Phase.Solid);
        Element c = new(name: "Carbon", mass: 12.011, symbol: "C", number: 6, phase: Phase.Solid);
        Element n = new(7, "N", "Nitrogen", 14.007, Phase.Gas);
        Element o = new(8, "O", "Oxygen", 15.999, Phase.Gas);
        Element f = new(9, "F", "Fluorine", 18.998, Phase.Gas);
        Element ne = new(10, "Ne", "Neon", 20.180, Phase.Gas);
        Element na = new(11, "Na", "Sodium", 22.990, Phase.Solid);
        Element mg = new(12, "Mg", "Magnesium", 24.305, Phase.Solid);
        Element al = new() { Phase = Phase.Solid, Symbol = "Al", AtomicNumber = 13, ElementName = "Aluminium", AtomicWeight = 26.982 };
        Element si = new(14, "Si", "Silicon", 28.085, Phase.Solid);
        Element p = new() { Symbol = "P", AtomicWeight = 30.974, AtomicNumber = 15, ElementName = "Phosphorus", Phase = Phase.Solid };
        Element s = new(16, "S", "Sulfur", 32.06, Phase.Solid);
        Element cl = new(17, "Cl", "Chlorine", 35.45, Phase.Gas);
        Element ar = new Element(18, "Ar", "Argon", 39.948, Phase.Gas);
        Element k = new Element(phase: Phase.Solid, number: 19, symbol: "K", name: "Potassium", mass: 39.098);
        Element ca = new(20, "Ca", "Calcium", 40.078, Phase.Solid);
        Element sc = new(number: 21, symbol: "Sc", phase: Phase.Solid, name: "Scandium", mass: 44.956);
        Element ti = new(name: "Titanium", number: 22, symbol: "Ti", mass: 47.867, phase: Phase.Solid);
        Element v = new Element() { AtomicNumber = 23, Symbol = "V", AtomicWeight = 50.942, ElementName = "Vanadium" };
        Element cr = new(number: 24, symbol: "Cr", phase: Phase.Solid, name: "Chromium", mass: 51.996);
    
        return cr;
    }
    
    Element elm = Prepare();
    
    Present(elm);
  9. To execute, on the main menu, click Debug -> Start Without Debugging:
    Chemistry
    --------------------------
    Symbol:        Cr
    Atomic Number: 24
    Element Name:  Chromium
    Atomic Weight: 51.996
    Phase/State:   Solid
    ==========================
    Press any key to close this window . . .

Setting a Null Object

You are not allowed to use an object that is not defined, such as an object that has not previously been initialized. If you do, you would receive an error.

If you declare a variable for a class but don't initialize it, the compiler reserves memory for the object but doesn't put any meaningful value in that memory area: the area is filled with garbage. That's why it is a good idea to (always) initialize the object. Still, sometimes when declaring the variable, you may not have the values necessary for the object. In this case, you can indicate that the object is null.

To support null objects, the C# language provides a keyword named null. To apply the nullity to an object, assign the null keyword to its declaration. Here is an example:

Microwave machine = null;

When necessary, you can ask the compiler to reset an object to nullity. To do this, assign null to the object. Here is an example:

using static System.Console;

void Present(Microwave mw)
{
    WriteLine("Microwave Oven");
    WriteLine("---------------------------------------");
    Write("Make and Model: ");
    Write(mw.Make);
    Write(" ");
    WriteLine(mw.Model);
    Write("Capacity:       ");
    Write(mw.Capacity);
    WriteLine(" cubic-foot");
    Write("Menu Options:   ");
    WriteLine(mw.MenuOptions);
    Write("Price:          ");
    WriteLine(mw.Price);
    WriteLine("=======================================");
}

Microwave machine = new Microwave()
{
    Make = "Farberware",
    Model = "FMO12AHTBSG",
    Capacity = 1.2,
    MenuOptions = 9,
    Price = 108.65
};

Present(machine);

machine = null;

public class Microwave
{
    public string Make { get; set; }
    public string Model { get; set; }
    public double Capacity { get; set; }
    public int MenuOptions { get; set; }
    public double Price { get; set; }
}

This would produce:

Microwave Oven
---------------------------------------
Make and Model: Farberware FMO12AHTBSG
Capacity:       1.2 cubic-foot
Menu Options:   9
Price:          108.65
=======================================

Press any key to close this window . . .

Returning a Null Object

When creating a method that is supposed to return a value, for some reason or another, you may not want the method to return an actual value. In this case, you can return null from the method. This can be done as follows:

using static System.Console;

void Present(Microwave mw)
{
    WriteLine("Microwave Oven");
    WriteLine("---------------------------------------");
    Write("Make and Model: ");
    Write(mw.Make);
    Write(" ");
    WriteLine(mw.Model);
    Write("Capacity:       ");
    Write(mw.Capacity);
    WriteLine(" cubic-foot");
    Write("Menu Options:   ");
    WriteLine(mw.MenuOptions);
    Write("Price:          ");
    WriteLine(mw.Price);
    WriteLine("=======================================");
}

Microwave Create()
{
    return null;
}

Microwave machine = Create();

Present(machine);

public class Microwave
{
    public string Make { get; set; }
    public string Model { get; set; }
    public double Capacity { get; set; }
    public int MenuOptions { get; set; }
    public double Price { get; set; }
}

This code would result in an error because you are attempting to use a null object.

On the other hand, when an application is running, one way or another, for any reason, an object may lose its values. For example, a function that is supposed to produce an object may fail to return a complete or appropriate object. In this case, when the object is accessed in your code, it may be holding a null value.

The Nullity of a Value

Introduction

When you declare a variable, you ask the compiler to reserve a certain area and amount of memory (in the computer memory or RAM) to eventually hold a value for that variable. Here is an example of declaring a variable:

using static System.Console;

int number;

WriteLine("Number: {0}", number);

When you have declared a variable like that, no clear value is stored in the reserved area of the computer memory. A value is referred to as null when it cannot be clearly determined. A null value is not 0 because 0 is an actual value. When declaring a variable, if you don't have a clear value for it, either you let the compiler know that you know what you are doing or you ask the compiler to treat the value as null.

Indicating a Null Value

In C#, normally, not all variables can hold null values. When declaring a variable, to indicate that it can hold either an actual value or it can be null, after its data type, add a question mark. You have two options.

You can assign null when declaring the variable. This would be done as follows:

data-type? variable-name = null

// You can use the variable}

Once again, if you plan to display the value of the variable, you must first specify a value for it. Here are examples:

using static System.Console;

string status = null;
string firstName = null, lastName = null;

// A floating-point variable of null type
double? hourlySalary = null;
// Another null floating-point variable
double? timeWorked = null;
// An integral variable of null type
int? category = null;

WriteLine("Employee Details");
WriteLine("==============================");
WriteLine("With null variables");
WriteLine("------------------------------");
WriteLine("Employee Name: " + firstName + " " + lastName);
WriteLine("Status:        " + status);
WriteLine("Hourly Rate:   {0}", hourlySalary);
WriteLine("Time Worked:   {0}", timeWorked);
WriteLine("Pay Category:  {0}", category);
WriteLine("==============================");

status = "Full-Time";
firstName = "Martial";
lastName = "Engolo";
category = 3;
timeWorked = 42.50;
hourlySalary = 22.27;

WriteLine("Employee Details");
WriteLine("==============================");
WriteLine("Variables with valid values");
WriteLine("------------------------------");
WriteLine("Employee Name: " + firstName + " " + lastName);
WriteLine("Status:        " + status);
WriteLine("Hourly Rate:   {0}", hourlySalary);
WriteLine("Time Worked:   {0}", timeWorked);
WriteLine("Pay Category:  {0}", category);
WriteLine("==============================");

This would produce:

Employee Details
==============================
With null variables
------------------------------
Employee Name:
Status:
Hourly Rate:
Time Worked:
Pay Category:
==============================
Employee Details
==============================
Variables with valid values
------------------------------
Employee Name: Martial Engolo
Status:        Full-Time
Hourly Rate:   22.27
Time Worked:   42.5
Pay Category:  3
==============================

Press any key to close this window . . .

As another option, you can assign null after the variable has been declared. This would be done as follows:

data-type? variable-name;

variable-name = null;

// You can use the variable

A Null String

When declaring a string variable, if you don't have a value for it, set it as null. Here are examples:

using static System.Console;

string status = null;
string firstName = null, lastName = null;
double hourlySalary = 22.27, timeWorked = 42.50;

status = "Full Time";
firstName = "Martial";
lastName = "Engolo";

WriteLine("Employee Details");
WriteLine("============================");
Write("Employee Name: ");
Write(firstName);
Write(" ");
WriteLine(lastName);
Write("Status: ");
WriteLine(status);
Write("Hourly Rate: ");
WriteLine(hourlySalary);
Write("Time Worked: ");
WriteLine(timeWorked);

Indicating a Null Object

We have seen that, when creating an object that doesn't yet have a value, to indicate this, assign null to the object. Furtheremore, to suggest to the compiler that you know what you are doing, apply the question mark to the class or data type. Here are examples:

int? number = null;
double? value = null;
string? name = null;
Element? atom = null;

internal class Element
{
    public string Symbol { get; set; }
    public string ElementName { get; set; }
    public int AtomicNumber { get; set; }
    public double AtomicWeight { get; set; }

    public Element(int number, string symbol, string name, double mass)
    {
        ElementName = name;
        AtomicWeight = mass;
        Symbol = symbol;
        AtomicNumber = number;
    }
}

Nullity and Conditional Statements

Comparing an Object to Nullity

Before using an object, you must make sure that it holds appropriate values, or at least that it is not null. Before using an object, to check whether it is null, using the equality operator, ==, compare it to null. Obviously, the reason you are checking the nullity of an object is so you can take an appropriate action one way or another. Here is an example:

The Nullity of a Value

using static System.Console;

void Present(MicrowaveOven mo)
{
    if(mo == null)
    {
        WriteLine("The object is null.");
        WriteLine("=======================================");
    }
    else
    {
        WriteLine("Microwave Oven");
        WriteLine("---------------------------------------");
        Write("Make and Model: ");
        Write(mo.Make);
        Write(" ");
        WriteLine(mo.Model);
        Write("Capacity:       ");
        Write(mo.Capacity);
        WriteLine(" cubic-foot");
        Write("Menu Options:   ");
        WriteLine(mo.MenuOptions);
        Write("Price:          ");
        WriteLine(mo.Price);
        WriteLine("=======================================");
    }
}

MicrowaveOven machine = null;

Present(machine);

machine = new MicrowaveOven()
{
    Make = "Farberware",
    Model = "FMO12AHTBSG",
    Capacity = 1.2,
    MenuOptions = 9,
    Price = 108.65
};

Present(machine);

machine = null;
Present(machine);

public class MicrowaveOven
{
    public string Make        { get; set; }
    public string Model       { get; set; }
    public double Capacity    { get; set; }
    public int    MenuOptions { get; set; }
    public double Price       { get; set; }
}

This would produce:

The object is null.
=======================================
Microwave Oven
---------------------------------------
Make and Model: Farberware FMO12AHTBSG
Capacity:       1.2 cubic-foot
Menu Options:   9
Price:          108.65
=======================================
The object is null.
=======================================
Press any key to close this window . . .

Comparing an Object for Non-Nullity

On the other hand, to find out whether an object is not null, you can use the != operator with the null keyword as the right operand. Here is an example:

using static System.Console;

void Present(MicrowaveOven mo)
{
    if(mo != null)
    {
        WriteLine("Microwave Oven");
        WriteLine("---------------------------------------");
        Write("Make and Model: ");
        Write(mo.Make);
        Write(" ");
        WriteLine(mo.Model);
        Write("Capacity:       ");
        Write(mo.Capacity);
        WriteLine(" cubic-foot");
        Write("Menu Options:   ");
        WriteLine(mo.MenuOptions);
        Write("Price:          ");
        WriteLine(mo.Price);
        WriteLine("=======================================");
    }
}

MicrowaveOven machine = null;

Present(machine);

machine = new MicrowaveOven()
{
    Make = "Black+Decker",
    Model = "EM720CB7",
    Capacity = 0.7,
    MenuOptions = 10,
    Price = 75.95
};

Present(machine);

machine = null;
Present(machine);

public class MicrowaveOven
{
    public string Make     { get; set; }
    public string Model    { get; set; }
    public double Capacity { get; set; }
    public int MenuOptions { get; set; }
    public double Price    { get; set; }
}

This would produce:

Microwave Oven
---------------------------------------
Make and Model: Black+Decker EM720CB7
Capacity:       0.7 cubic-foot
Menu Options:   10
Price:          75.95
=======================================
Press any key to close this window . . .

The Nullity of a Value

Besides the != operator, the C# language provides an operator named not. You can use it to find out whether an argument or object is null or not.

Practical LearningPractical Learning: Comparing an Object for Non-Nullity

  1. Change the PeriodicTable class as follows:
    using Chemistry6;
    using static System.Console;
    
    void Present(Element obj)
    {
        if (obj is not null)
        {
            WriteLine("Chemistry");
            WriteLine("--------------------------");
            WriteLine("Symbol:        " + obj.Symbol);
            WriteLine($"Atomic Number: {obj.AtomicNumber}");
            WriteLine("Element Name:  " + obj.ElementName);
            WriteLine($"Atomic Weight: " + obj.AtomicWeight);
            WriteLine("Phase/State:   " + obj.Phase);
            Write("==========================");
        }
    }
    
    Element Prepare()
    {
        // . . .
        Element mn = new(25, "Mn", "Manganese", 54.938, Phase.Solid);
    
        return mn;
    }
    
    Element elm = Prepare();
    
    Present(elm);
  2. To execute, on the main menu, click Debug -> Start Without Debugging:
    Chemistry
    --------------------------
    Symbol:        Mn
    Atomic Number: 25
    Element Name:  Manganese
    Atomic Weight: 54.938
    Phase/State:   Solid
    ==========================
    Press any key to close this window . . .
  3. Start a new Console App that supports .NET 7.0 (Standard Term Support) and named StellarWaterPoint3

Switching to a Null Case

When working on a switch statement, you may have a situation where the variable considered is not holding a known value or its value is clearly null. In this situation, the C# language allows you to consider a case that is null. To do this, in the switch statement, create a case whose value is null. Here is an example:

using static System.Console;

Element Create()
{
    int? number = null;
    Element selected = null;

    Element h = new Element(1, "H", "Hydrogen", 1.008);
    Element he = new Element(2, "He", "Helium", 4.002602);
    Element li = new Element(3, "Li", "Lithium", 6.94);
    Element be = new Element(4, "Be", "Beryllium", 9.0121831);
    Element b = new Element(5, "B", "Boron", 10.81);

    switch (number)
    {
        case 2:
            selected = he;
            break;
        case 3:
            selected = li;
            break;
        case 4:
            selected = be;
            break;
        case 5:
            selected = b;
            break;
        case null:
            selected = h;
            break;
    }

    return selected;
}

Element elm = Create();

WriteLine("=========================");
WriteLine("Chemistry");
WriteLine("-------------------------");
WriteLine("Symbol:        {0}", elm.Symbol);
WriteLine("Atomic Number: {0}", elm.AtomicNumber);
WriteLine("Element Name:  {0}", elm.ElementName);
WriteLine("Atomic Weight: {0}", elm.AtomicWeight);
WriteLine("=========================");

internal class Element
{
    public string Symbol { get; set; }
    public string ElementName { get; set; }
    public int AtomicNumber { get; set; }
    public double AtomicWeight { get; set; }

    public Element(int number, string symbol, string name, double mass)
    {
        ElementName = name;
        AtomicWeight = mass;
        Symbol = symbol;
        AtomicNumber = number;
    }
}

This would produce:

=========================
Chemistry
-------------------------
Symbol:        H
Atomic Number: 1
Element Name:  Hydrogen
Atomic Weight: 1.008
=========================

Press any key to close this window . . .

By the way, the null case can be the first, it can be the last, or it can appear in any position within the switch statment.

Considering Default and Null Cases

When creating a switch statement, you should predict as many cases as possible. We already know that you can create a default case that would embrace the value that matches none of the others; but the default case assumes that there is a valid value that none of the other cases is holding. We saw that this is not always the case: there could be an unknown or invalid value. For example, you can consider a series of numbers from 10, in which case 12 is not included but 12 is a valid value; but a null case would mean that you don't have a number at all. For this type of scenario, you should consider using both a null and a default cases. By the way, those cases can appear in any order. Here is an example:

using static System.Console;

Element Create()
{
    int? number = null;
    Element selected = null;

    Element h  = new Element(1, "H",  "Hydrogen",   1.008);
    Element he = new Element(2, "He", "Helium",     4.002602);
    Element li = new Element(3, "Li", "Lithium",    6.94);
    Element be = new Element(4, "Be", "Beryllium",  9.0121831);
    Element b  = new Element(5, "B",  "Boron",     10.81);
    Element c  = new Element(6, "C",  "Carbon",    12.011);

    switch (number)
    {
        case 2:
            selected = he;
            break;
        case 3:
            selected = li;
            break;
 
        default:
            selected = c;
            break;
 
        case 4:
            selected = be;
            break;
        case 5:
            selected = b;
            break;
        
        case null:
            selected = h;
            break;
    }

    return selected;
}

Element elm = Create();

WriteLine("=========================");
WriteLine("Chemistry");
WriteLine("-------------------------");
WriteLine("Symbol:        {0}", elm.Symbol);
WriteLine("Atomic Number: {0}", elm.AtomicNumber);
WriteLine("Element Name:  {0}", elm.ElementName);
WriteLine("Atomic Weight: {0}", elm.AtomicWeight);
WriteLine("=========================");

internal class Element
{
    public string Symbol { get; set; }
    public string ElementName { get; set; }
    public int AtomicNumber { get; set; }
    public double AtomicWeight { get; set; }

    public Element(int number, string symbol, string name, double mass)
    {
        ElementName = name;
        AtomicWeight = mass;
        Symbol = symbol;
        AtomicNumber = number;
    }
}

Checking the Compatibility of an Object

The equality operator is used to find out whether an object is equal to a certain value. Because an application may deal with various types of values, an alternative is to find out whether a certain object is compatible with another. To perform this comparison, you use a Boolean operator named is. There are various scenarios you can use this operator. The formula to find out whether an object is null is:

instance-object is null

You can use an if conditional statement to obtain this information. Here is an example:

using static System.Console;

void Present(MicrowaveOven mo)
{
    if(mo is null)
    {
        WriteLine("There is no machine to show.");
        WriteLine("=======================================");
    }
    else
    {
        WriteLine("Microwave Oven");
        WriteLine("---------------------------------------");
        Write("Make and Model: ");
        Write(mo.Make);
        Write(" ");
        WriteLine(mo.Model);
        Write("Capacity:       ");
        Write(mo.Capacity);
        WriteLine(" cubic-foot");
        Write("Menu Options:   ");
        WriteLine(mo.MenuOptions);
        Write("Price:          ");
        WriteLine(mo.Price);
        WriteLine("=======================================");
    }
}

MicrowaveOven machine = null;

Present(machine);

machine = new MicrowaveOven()
{
    Make = "Aicok",
    Model = "EM131A5C-BS",
    Capacity = 1.1,
    MenuOptions = 11,
    Price = 79.95
};

Present(machine);

machine = null;
Present(machine);

public class MicrowaveOven
{
    public string Make { get; set; }
    public string Model { get; set; }
    public double Capacity { get; set; }
    public int MenuOptions { get; set; }
    public double Price { get; set; }
}

This would produce:

There is no machine to show.
=======================================
Microwave Oven
---------------------------------------
Make and Model: Aicok EM131A5C-BS
Capacity:       1.1 cubic-foot
Menu Options:   11
Price:          79.95
=======================================
There is no machine to show.
=======================================
Press any key to close this window . . .

The Nullity of a Value

Checking the Type of an Object

We have already been introduced to a data type named object. This is the most fundamental type in C# (and the .NET Framework) and, in some cases, it can be used in place of any data type. As a matter of fact, if you are creating a function that would treat various types of objects, you can pass an object type to it. Then, in the body of the function, before doing anything, find out what type was passed as argument. To do that, use the is operator to compare the argument to the desired type. Here is an example:

using static System.Console;

void Present(object obj)
{
    if (obj is Microwave)
    {
        Microwave mw = (Microwave)obj;

        WriteLine("Make and Model:    " + mw.Make + " " + mw.Model);
        WriteLine("Capacity:          {0}", mw.Capacity);
        WriteLine("Microwave Options: {0}", mw.MenuOptions);
        WriteLine("==========================================");
    }
}

Microwave machine = null;

Present(machine);

machine = new Microwave()
{
    Make        = "Farberware",
    Model       = "FMO12AHTBSG",
    Capacity    = 1.2,
    MenuOptions = 9
};

Person friend = new Person();
Present(friend);

Present(machine);

Bicycle voyage = new Bicycle();
Present(voyage);

public class Microwave
{
    public string Make { get; set; }
    public string Model { get; set; }
    public double Capacity { get; set; }
    public int MenuOptions { get; set; }
}

public class Person
{
    public string Name { get; set; }
}

public class Bicycle
{
    public int    Speeds { get; set; }
    public double Price  { get; set; }
}

Practical LearningPractical Learning: Ending the Lesson


Previous Copyright © 2001-2023, FunctionX Wednesday 01 June 2022 Next