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

@page
@model PracticalLearning.Pages.NullityModel
@functions{
    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; }
    }
}

@{
    MicrowaveOven machine = null;
}

@if(mo == null)
{
    <p>The object is null.</p>
    <p>=======================================</p>
}
else
{
    <p>Microwave Oven</p>
    <p>---------------------------------------</p>
    <p>Make and Model: @machine.Make @machine.Model</p>
    <p>Capacity:       @machine.Capacity cubic-foot</p>
    <p>Menu Options:   @machine.MenuOptions</p>
    <p>Price:          @machine.Price</p>
    <p>=======================================</p>
}

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

@if(mo == null)
{
    <p>The object is null.</p>
    <p>=======================================</p>
}
else
{
    <p>Microwave Oven</p>
    <p>---------------------------------------</p>
    <p>Make and Model: @machine.Make @machine.Model</p>
    <p>Capacity:       @machine.Capacity cubic-foot</p>
    <p>Menu Options:   @machine.MenuOptions</p>
    <p>Price:          @machine.Price</p>
    <p>=======================================</p>
}

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

=======================================

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:

@page
@model PracticalLearning.Pages.NullityModel
@{
    MicrowaveOven machine = new MicrowaveOven()
    {
        Make = "Farberware",
        Model = "FMO12AHTBSG",
        Capacity = 1.2,
        MenuOptions = 9,
        Price = 108.65
    };
}

@functions{
    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; }
    }
}

@if(machine != null)
{
    <p>Microwave Oven</p>
    <p>---------------------------------------</p>
    <p>Make and Model: @machine.Make @machine.Model</p>
    <p>Capacity:       @machine.Capacity cubic-foot</p>
    <p>Menu Options:   @machine.MenuOptions</p>
    <p>Price:          @machine.Price</p>
    <p>=======================================</p>
}
else
{
    <p>The object is null.</p>
    <p>=======================================</p>
}

@if(machine != null)
{
    <p>The object is null.</p>
    <p>=======================================</p>
}
else
{
    <p>Microwave Oven</p>
    <p>---------------------------------------</p>
    <p>Make and Model: @machine.Make @machine.Model</p>
    <p>Capacity:       @machine.Capacity cubic-foot</p>
    <p>Menu Options:   @machine.MenuOptions</p>
    <p>Price:          @machine.Price</p>
    <p>=======================================</p>
}

This would produce:

Microwave Oven

---------------------------------------

Make and Model: Farberware FMO12AHTBSG

Capacity: 1.2 cubic-foot

Menu Options: 9

Price: 108.65

=======================================

The object is null.

=======================================

The Nullity of a Value

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:

@page
@model PracticalLearning.Pages.NullityModel
@{
    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;
    }
}

@functions{
    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;
        }
    }
}

<pre>=========================
Chemistry
-------------------------
Symbol:        @selected.Symbol
Atomic Number: @selected.AtomicNumber
Element Name:  @selected.ElementName
Atomic Weight: @selected.AtomicWeight
=========================</pre>
            selected = h;
            break;
    }
}

@functions{
    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;
        }
    }
}

<pre>=========================
Chemistry
-------------------------
Symbol:        @selected.Symbol
Atomic Number: @selected.AtomicNumber
Element Name:  @selected.ElementName
Atomic Weight: @selected.AtomicWeight
=========================</pre>

This would produce:

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

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.

Checking the Compatibility of Objects

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.

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:

@page
@model PracticalLearning.Pages.NullityModel
@{
    MicrowaveOven machine = new()
    {
        Make = "Aicok",
        Model = "EM131A5C-BS",
        Capacity = 1.1,
        MenuOptions = 11,
        Price = 79.95
    };
}

@functions{
    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; }
    }
}

@if(machine is null)
{
    <p>There is no machine to show.</p>
    <p>=======================================</p>
}
else
{
    <p>Microwave Oven</p>
    <p>-------------------------------------------------</p>
    <p>Make and Model: @machine.Make @machine.Model</p>
    <p>Capacity:       @machine.Capacity cubic-foot</p>
    <p>Menu Options:   @machine.MenuOptions</p>
    <p>Price:          @machine.Price</p>
    <p>=============================</p>
}

This would produce:

Microwave Oven

---------------------------------------

Make and Model: Aicok EM131A5C-BS

Capacity: 1.1 cubic-foot

Menu Options: 11

Price: 79.95

=======================================

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 library) 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.

Checking the Negative Compatibility

If you want to check that a certain object is not compatible with a class you are concerned with, you can use an operator named an operator named not. You can use it to find out whether an argument or object is null or not. To use the not operator, precede it with the is operator in a conditional statement. Here is an example:

@page
@model PracticalLearning.Pages.NullityModel
@{
    MicrowaveOven machine = new MicrowaveOven()
    {
        Make = "Black+Decker",
        Model = "EM720CB7",
        Capacity = 0.7,
        MenuOptions = 10,
        Price = 75.95
    };
}

@functions{
    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; }
    }
}

@if(machine is not null)
{
<pre>Microwave Oven
---------------------------------------
Make and Model: @machine.Make @machine.Model
Capacity:       @machine.Capacity cubic-foot
Menu Options:   @machine.MenuOptions
Price:          @machine.Price
=======================================</pre>
}
else
{
<pre>The object is null.
=======================================</pre>

This would produce:

Microwave Oven
---------------------------------------
Make and Model: Black+Decker EM720CB7
Capacity:       0.7 cubic-foot
Menu Options:   10
Price:          75.95
=======================================

The Nullity and Functions or Methods

Returning a Null Object

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

@functions{
    public class Microwave
    {
        public string Make { get; set; }
    }

    Microwave Create()
    {
        return null;
    }
}

This code would result in an error because you are attempting to use a null object. Normally, sometimes when you work in a function that must return an object, you check some conditions related to that object. Then, if the object respond positively to a certain condition, you can return a valid object; but if the object doesn't respond to another or a certain condition, you can return null. Here is an example:

@page
@model Valuable.Pages.FormattingValuesModel

@{
    Microwave machine = Create();
}

@functions{
    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 length, double width, double height) Exterior { get; set; }
        public double Price       { get; set; }
    }

    Microwave Create()
    {
        Microwave mw = new();

        mw.Make        = "Frigidaire ";
        mw.Model       = "VIPRB-VIPRB";
        mw.Capacity    = 1.4;
        mw.MenuOptions = 10;
        mw.Price       = 138.95;
        mw.Exterior    = (24.49, 18.34, 15.04);

        if (mw.Price is >= 150)
            return null;
        else
            return mw;
    }
}

@if(machine is not null)
{
    <p>Microwave Oven</p>
    <p>---------------------------------------</p>
    <p>Make and Model: @machine.Make @machine.Model</p>
    <p>Capacity:       @machine.Capacity cubic-foot</p>
    <p>Menu Options:   @machine.MenuOptions</p>
    <p>Dimensions:     @machine.Exterior</p>
    <p>Price:          @machine.Price</p>
    <p>=======================================</p>
}
else
{
    <p>There is no microwave information to display</p>
}

This would produce:

Microwave Oven

---------------------------------------

Make and Model: Frigidaire VIPRB-VIPRB

Capacity: 1.4 cubic-foot

Menu Options: 10

Dimensions: (24.49, 18.34, 15.04)

Price: 138.95

=======================================

Here is another version of the program:

@page
@model Valuable.Pages.FormattingValuesModel

@{
    Microwave machine = Create();
}

@functions{
    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 length, double width, double height) Exterior { get; set; }
        public double Price       { get; set; }
    }

    Microwave Create()
    {
        Microwave mw = new()
        {
            Make        = "Hamilton Beach",
            Model       = "EM145AAK-P",
            Capacity    = 1.6,
            MenuOptions = 10,
            Price       = 158.85,
            Exterior    = (21.67, 19.50, 12.88)
        };

        if (mw.Price is >= 150)
            return null;
        else
            return mw;
    }
}

@if(machine is not null)
{
    <p>Microwave Oven</p>
    <p>---------------------------------------</p>
    <p>Make and Model: @machine.Make @machine.Model</p>
    <p>Capacity:       @machine.Capacity cubic-foot</p>
    <p>Menu Options:   @machine.MenuOptions</p>
    <p>Dimensions:     @machine.Exterior</p>
    <p>Price:          @machine.Price</p>
    <p>=======================================</p>
}
else
{
    <p>There is no microwave information to display</p>
}

This would produce:

There is no microwave information to display

Passing a Null Object

We have already seen that, if you have a function or method that uses a parameter that is a class type, in the body of the function, before using the argument, you can check whether it holds a valid value. Here is an example:

@page
@model Valuable.Pages.FormattingValuesModel

@{
    Microwave machine = Create();

    string decision = Validate(machine);
}

@functions{
    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; }
    }

    Microwave Create()
    {
        Microwave mw = new();

        mw.Make = "Farberware";
        mw.Model = "FMO12AHTBSG";
        mw.Capacity = 1.7;
        mw.MenuOptions = 6;
        mw.Price = 188.95;

        if (mw.Price is >= 100)
            return null;

        return mw;
    }

    string Validate(Microwave something)
    {
        if (something is not null)
            return "The item will be exchanged";
        else
            return "The customer claims to have bought the wrong item.";
    }
}

@if(machine is not null)
{
    <p>Microwave Oven</p>
    <p>---------------------------------------</p>
    <p>Make and Model: @machine.Make @machine.Model</p>
    <p>Capacity:       @machine.Capacity cubic-foot</p>
    <p>Menu Options:   @machine.MenuOptions</p>
    <p>Price:          @machine.Price</p>
    <p>=======================================</p>
}
else
{
    <p>There is no microwave information to display</p>
}

<p>Decision: @decision</p>

This would produce:

There is no microwave information to display

Decision: The customer claims to have bought the wrong item.

On the other hand, when you are calling a function that uses an argument of an object type, if for some reason you don>t to (or you can't) pass a valid argument, you can pass a null object. Here is an example:

@page
@model Valuable.Pages.FormattingValuesModel

@{
    Microwave machine = Create();

    string decision = Validate(null);
}

@functions{
    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; }
    }

    Microwave Create()
    {
        Microwave mw = new();

        mw.Make = "Farberware";
        mw.Model = "FMO12AHTBSG";
        mw.Capacity = 1.7;
        mw.MenuOptions = 6;
        mw.Price = 88.95;

        if (mw.Price is >= 100)
            return null;

        return mw;
    }

    string Validate(Microwave something)
    {
        if (something is not null)
            return "The item will be exchanged";
        else
            return "The customer claims to have bought the wrong item.";
    }
}

@if(machine is not null)
{
    <p>Microwave Oven</p>
    <p>---------------------------------------</p>
    <p>Make and Model: @machine.Make @machine.Model</p>
    <p>Capacity:       @machine.Capacity cubic-foot</p>
    <p>Menu Options:   @machine.MenuOptions</p>
    <p>Price:          @machine.Price</p>
    <p>=======================================</p>
}
else
{
    <p>There is no microwave information to display</p>
}

<p>Decision: @decision</p>

This would produce:

Microwave Oven

---------------------------------------

Make and Model: Farberware FMO12AHTBSG

Capacity: 1.7 cubic-foot

Menu Options: 6

Price: 88.95

=======================================

Decision: The customer claims to have bought the wrong item.

Nullity Operators

The Null Forgiving Operator

We already know that, before using a variable you have or are declaring, you must initialize that variable. Here is an example:

@page
@model PracticalLearning.Pages.NullityModel
@{
    int number = 100;
}

<pre>Number: @number</pre>

In this case, you know for sure that your variable has a value, because you made sure to assign a value to the variable before using it. In some cases, the value of a variable may come by other means, such as from user (who may receive a request or prompt to type a value) or from a stream (computer memory, network, internet, etc). When that's the case, the compiler may issue a warning just to ask you whether you know for sure that the value of the variable or object will be provided. In most cases, this is a soft warning that will not produce an error but should be taken care of. In many cases, you can ignore that warning. The rule of thumb is that you should not ignore warnings, or at least you should always know the reason for a warning and probably take care of it.

The null-forgiving operator allows you to indicate to the compiler that you are aware that the variable or object may be holding a null value but you know what you are doing. The null-forgiving operator is !. To apply it, simply type it on the right side of the object or value. Here is an example:

@page
@model PracticalLearning.Pages.NullityModel
@{
    int number = 100!;
}

&lt;pre&gt;Number: @number&lt;/pre&gt;

Normally, the null-forgiving operator has no effect on a variable of primitive type when the variable is initialized immediately after you have declared it. If the value is supposed to be provided to the object or variable other than when initializing the object or variable, then the compiler would issue a warning. That's when you should apply the null-forgiving operator.

The Null-Conditional Operator

Consider a class used to describe some houses:

public class House
{
    public int Bedrooms;

    public House()
    {
        Bedrooms = 1;
    }
}

We already saw how to find out whether an object of such a class is currently valid. Here is an example:

int beds = -1;
House habitat = null;
Description desc = new Description();

if (habitat == null)
{
    beds = 0;
}
else
{
    beds = habitat.Bedrooms;
}

In this case, we are trying to access a member of the class (getting the value of a property) only if the object is null. To simplify this operation, you can use the null-conditional operator represented as ?. (the question mark immediately followed by a period). To apply it, use it to access the member of a class. Here is an example:

int ? beds = 0;
House habitat = null;
Description desc = new Description();

beds = habitat?.Bedrooms;

Here is another version of the code:

int ?beds = -1;
Description desc = new Description();
House habitat = new House();
habitat.Bedrooms = 5;

beds = habitat?.Bedrooms;

The ?. operator checks whether the variable on its left is currently holding a null value. If it is, nothing happens. If it doesn't, then the member on its right is accessed and the operation that must be performed proceeds.

The Null Coalescing Operator

The ?. operator is used to simply check the nullity of a variable. You must apply the subsequent statement separately. To combine the ?. operation and its subsequent statement, you use the null coalescent operator represented as ?? (Two question marks). To apply it, type it after the condition followed by the desired statement. Here is an example:

int ?beds = -1;
Description desc = new Description();
House habitat = null;

beds = habitat?.Bedrooms ?? 0;

This code states that if the habitat object is null, the beds variable should be assigned 0. If the habitat object is not null, then the beds variable should receive a value from the designated property of the House class.


Previous Copyright © 2001-2022, FunctionX Sunday 14 November 2021 Next