Home

Structures

 

Fundamentals of Structures

 

Introduction

A structure is an enhanced version of the primitive data types we have used in previous lessons. Like a class, a structure is created from one variable of a primitive type or by combining various variables of primitive types.

To create a structure, you use the same formula as for a class but with the struct keyword. Here is an example of a structure:

struct Integer
{
}

Like a class, a structure can have fields. They are listed in the body of the structure. Here is an example:

struct Integer
{
    private int val;
}

A structure can also have properties. Here is an example:

struct Integer
{
    private int val;

    public int Value
    {
        get { return val; }
        set { val = value; }
    }
}

A structure can also have methods. Here is an example:

struct Integer
{
    private int val;

    public int Value
    {
        get { return val; }
        set { val = value; }
    }

    public int Read()
    {
        return int.Parse(Console.ReadLine());
    }
}

Structure Declaration

Like any other data type, to use a structure, you can first declare a variable from it. To allocation memory for a variable declared from a structure, use the new operator as done for a class. Here is an example:

using System;

struct Integer
{
    private int val;

    public int Value
    {
        get { return val; }
        set { val = value; }
    }

    public int Read()
    {
        return int.Parse(Console.ReadLine());
    }
}

class Program
{
    static int Main()
    {
        Integer Natural = new Integer();
	return 0;
    }
}

As done for variables of the other types and as seen for classes, to declare a variable for a structure, you can use the var keyword. After declaring the variable, you can use the object the same way you would a class. You can access its members (fields, properties, and methods) using the period operator. Here is an example:

using System;

struct Integer
{
    private int val;

    public int Value
    {
        get { return val; }
        set { val = value; }
    }

    public int Read()
    {
        return int.Parse(Console.ReadLine());
    }
}

class Program
{
    static int Main()
    {
        var Natural = new Integer();

        Console.Write("Enter a natural number: ");
        // Accessing a property of the structure
        Natural.Value =
        // Calling a method of the structure
        Natural.Read();

        Console.WriteLine("The value you entered was: {0}", Natural.Value);
	return 0;
    }
}

Here is an example of running the program:

Enter a natural number: 248
The value you entered was: 248
Press any key to continue . . .

Although there are many similarities in the behaviors of classes and structures, you should use a structure when the object you are creating is meant to represent relatively small values. Like primitive data types and unlike a class, a structure is a value type. 

Techniques of Using Structures

 

A Structure as a Property

Once a structure exists, you can use it like a data type. For example, you can create a property that is a structure type. The rules are the same we reviewed for creating a property of a class. After creating the property, you can use it as you see fit. Here is an example:

using System;

public struct Real
{
    private double val;

    public double Value
    {
        get { return val; }
        set { val = value; }
    }

    public double Read()
    {
        return double.Parse(Console.ReadLine());
    }
}

public struct Rectangle
{
    Real len;
    Real hgt;

    public Real Length
    {
        get { return len; }
        set { len = value; }
    }

    public Real Height
    {
        get { return hgt; }
        set { hgt = value; }
    }

    public void CreateRectangle()
    {
        Real rat = new Real();

        Console.WriteLine("Enter the dimensions of the rectangle");
        Console.Write("Enter the length: ");
        len.Value = rat.Read();
        Console.Write("Enter the height: ");
        hgt.Value = rat.Read();
    }
}

public class Program
{
    static int Main()
    {
        var Rect = new Rectangle();

        Rect.CreateRectangle();
        Console.WriteLine();

        Console.WriteLine("Rectangle Characteristics");
        Console.WriteLine("Length:    {0}", Rect.Length.Value);
        Console.WriteLine("Height:    {0}", Rect.Height.Value);
        Console.WriteLine("Perimeter: {0}",
            (Rect.Length.Value + Rect.Height.Value) * 2);
        Console.WriteLine("Area:      {0}",
            Rect.Length.Value * Rect.Height.Value);

        return 0;
    }
}

Here is an example of running the program:

Enter the dimensions of the rectangle
Enter the length: 44.84
Enter the height: 26.75

Rectangle Characteristics
Length:    44.84
Height:    26.75
Perimeter: 143.18
Area:      1199.47
Press any key to continue . . .

Returning a Structure From a Method

Like regular data type or a class, a structure can serve as the return type of a method.  The rules are more related to those of a class. When creating the method, type the name of the structure on the left side of the name of the method. In the body of the method, implement the desired behavior. Before exiting the method, make sure you return a valid value that is of the type of the structure. When a method returns a value of the type of a structure, you can assign the method to a variable of the type of the structure.

Here is an example of implementing a method that returns a structure type, including calling the method and using its value:

using System;

public struct Real
{
    private double val;

    public double Value
    {
        get { return val; }
        set { val = value; }
    }

    public double Read()
    {
        return double.Parse(Console.ReadLine());
    }
}

public struct Rectangle
{
    Real len;
    Real hgt;

    public Real Length
    {
        get { return len; }
        set { len = value; }
    }

    public Real Height
    {
        get { return hgt; }
        set { hgt = value; }
    }

    public void CreateRectangle()
    {
        Real rat = new Real();

        Console.WriteLine("Enter the dimensions of the rectangle");
        len = GetLength();
        Console.Write("Enter the height: ");
        hgt.Value = rat.Read();
    }

    public Real GetLength()
    {
        Real rat = new Real();

        Console.Write("Enter the length: ");
        rat.Value = rat.Read();
        return rat;
    }
}

public class Program
{
    static int Main()
    {
        var Rect = new Rectangle();

        Rect.CreateRectangle();
        Console.WriteLine();

        Console.WriteLine("Rectangle Characteristics");
        Console.WriteLine("Length:    {0}", Rect.Length.Value);
        Console.WriteLine("Height:    {0}", Rect.Height.Value);
        Console.WriteLine("Perimeter: {0}",
            (Rect.Length.Value + Rect.Height.Value) * 2);
        Console.WriteLine("Area:      {0}",
             Rect.Length.Value * Rect.Height.Value);

        return 0;
    }
}

Here is an example of running the application:

Enter the dimensions of the rectangle
Enter the length: 36.04
Enter the height: 22.86

Rectangle Characteristics
Length:    36.04
Height:    22.86
Perimeter: 117.8
Area:      823.8744
Press any key to continue . . .

Passing a Structure as Argument

Like a data type, a structure can be passed as argument to a method. The argument is primarily passed as done for a class. After passing the argument, in the body of the method, you can access the public members of the structure, using the period operator. Here is an example:

using System;

public struct Real
{
    private double val;

    public double Value
    {
        get { return val; }
        set { val = value; }
    }

    public double Read()
    {
        return double.Parse(Console.ReadLine());
    }
}

public struct Rectangle
{
    Real len;
    Real hgt;

    public Real Length
    {
        get { return len; }
        set { len = value; }
    }

    public Real Height
    {
        get { return hgt; }
        set { hgt = value; }
    }

    public void CreateRectangle()
    {
        Real rat = new Real();

        Console.WriteLine("Enter the dimensions of the rectangle");
        len = GetLength();
        Console.Write("Enter the height: ");
        hgt.Value = rat.Read();
    }

    public Real GetLength()
    {
        Real rat = new Real();

        Console.Write("Enter the length: ");
        rat.Value = rat.Read();
        return rat;
    }
}

public class Program
{
    public static void ShowCharacteristics(Rectangle rect)
    {
        Console.WriteLine("Rectangle Characteristics");
        Console.WriteLine("Length:    {0}", rect.Length.Value);
        Console.WriteLine("Height:    {0}", rect.Height.Value);
        Console.WriteLine("Perimeter: {0}",
		(rect.Length.Value + rect.Height.Value) * 2);
        Console.WriteLine("Area:      {0}",
		rect.Length.Value * rect.Height.Value);
    }
    static int Main()
    {
        var Rect = new Rectangle();
        Rect.CreateRectangle();
        
        Console.WriteLine();
        ShowCharacteristics(Rect);

        return 0;
    }
}

Here is an example of running the program:

Enter the dimensions of the rectangle
Enter the length: 114.55
Enter the height: 82.72

Rectangle Characteristics
Length:    114.55
Height:    82.72
Perimeter: 394.54
Area:      9475.576
Press any key to continue . . .

When you pass a structure to a method as we did above, it referred to as passing by value. A copy of the value of the structure is passed to the method. If the method modifies the argument, the original variable would stay intact. If you want the method to modify the value of the structure, you can pass the argument by reference. You can do this using the (rules of the) ref and the out keywords.

Here is an example of passing a structure by reference using the ref keyword:

using System;

public struct Real
{
    private double val;

    public double Value
    {
        get { return val; }
        set { val = value; }
    }

    public double Read()
    {
        return double.Parse(Console.ReadLine());
    }
}

public struct Rectangle
{
    Real len;
    Real hgt;

    public Real Length
    {
        get { return len; }
        set { len = value; }
    }

    public Real Height
    {
        get { return hgt; }
        set { hgt = value; }
    }

    public void CreateRectangle()
    {
        Console.WriteLine("Enter the dimensions of the rectangle");
        len = GetLength();
        GetHeight(ref hgt);
    }

    public Real GetLength()
    {
        Real rat = new Real();

        Console.Write("Enter the length: ");
        rat.Value = rat.Read();
        return rat;
    }

    public void GetHeight(ref Real rl)
    {
        Real rat = new Real();

        Console.Write("Enter the height: ");
        rl.Value = rat.Read();
    }
}

public class Program
{
    static int Main()
    {
        Rectangle rect = new Rectangle();

        rect.CreateRectangle();
        Console.WriteLine();

        Console.WriteLine("Rectangle Characteristics");
        Console.WriteLine("Length:    {0}", rect.Length.Value);
        Console.WriteLine("Height:    {0}", rect.Height.Value);
        Console.WriteLine("Perimeter: {0}",
            (rect.Length.Value + rect.Height.Value) * 2);
        Console.WriteLine("Area:      {0}",
            rect.Length.Value * rect.Height.Value);

        return 0;
    }
}

Here is an example of running the program:

Enter the dimensions of the rectangle
Enter the length: 75.82
Enter the height: 55.64

Rectangle Characteristics
Length:    75.82
Height:    55.64
Perimeter: 262.92
Area:      4218.6248
Press any key to continue . . .
 

Built-In Structures: The Integral Data Types

 

Introduction

The C# language (actually the .NET Framework) treats each primitive data type as a class. In fact, each data type was created as a structure. Some characteristics are common to many of these structures while some other aspects are unique to some others.

To support the routine operations of regular variables, each structure that represents a primitive type is equipped with some member variables and methods.

Conversion to a String

With a value of a primitive type, at one time or another, you may need to convert the value of a variable from its type to a string. To support this, each structure of a primitive type is equipped with a method named ToString. This method is overloaded with various versions. One of the versions of this method takes no argument. The syntax of this method is:

public override string ToString();

Another version of this method takes as argument a string. This string holds an expression used to format the value of the variable that called the method. The syntax of this method is:

public string ToString(string format);

You can pass the desired string to format the value to be displayed.

Parsing a String

In Lesson 5, we saw how to retrieve a value from the console and convert it to the desired value. To support this operation, each structure of a primitive data type is equipped with a static method named Parse. The syntaxes of this method are:

byte
public static byte Parse(string s);
sbyte
public static sbyte Parse(string s);
short
public static short Parse(string s);
ushort <=> UInt16
public static ushort Parse(string s);
int <=> Int32
public static int Parse(string s);
uint <=> UInt32
public static uint Parse(string s);
long <=> Int64
public static long Parse(string s);
unsigned long <=> uint64
public static ulong Parse(string s);

 Here is an example of calling this method:

using System;

class Program
{
    static int Main()
    {
        double value = 0;

        Console.Write("Enter a Value: ");
        value = double.Parse(Console.ReadLine());

        Console.WriteLine("Value Entered: {0}", value);

        return 0;
    }
}

Here is an example of executing the program:

Enter a Value: 245.85
Value Entered: 245.85
Press any key to continue . . .

You can also parse a value that is not primarily known. To support values other than byte types, you can use another version of the Equals() method that takes as argument an object type. The syntaxes of this version of the method are:

byte
public static byte Parse(string s)
sbyte
public static sbyte Parse(string s)
short
public static short Parse(string s)
ushort <=> UInt16
public static ushort Parse(string s)
int <=> Int32
public static int Parse(string s)
uint <=> UInt32
public static uint Parse(string s)
long <=> Int64
public static long Parse(string s)
unsigned long <=> uint64
public static ulong Parse(string s)

When calling this method, if a bad value is passed to the Parse() method, for example if the user enters an invalid value to a double.Parse(Console.ReadLine()) call, the program produces an error (in Lesson 17, we will learn that the program throws an exception). To assist you with this type of problem, each structure of a primitive type is equipped with a method named TryParse. This method is overloaded with two versions that each returns a bool. One of the versions of this method takes two arguments: a string and a variable passed as an out reference. The syntaxes of this method are:

byte
public static bool TryParse(string s, out byte result)
sbyte
public static bool TryParse(string s, out sbyte result)
short
public static bool TryParse(string s, out short result)
ushort <=> UInt16
public static bool TryParse(string s, out ushort result)
int <=> Int32
public static bool TryParse(string s, out int result)
uint <=> UInt32
public static bool TryParse(string s, out uint result)
long <=> Int64
public static bool TryParse(string s, out long result)
unsigned long <=> uint64
public static bool TryParse(string s, out ulong result)

Based on this, if a double variable calls this method, the first argument is passed a string and the second argument is passed as an out double. This means that the second argument is returned from the method also.

When the TryParse() method is called:

  • If the first argument passed to the method is valid, the method returns two values: true and the entered value is stored in the out argument
  • If the value of the first argument is invalid, the method returns false and the default value of the data type is stored in the out argument. For example, if the variable that called the method is on type int but the user entered the wrong value, the method returns two values: false and 0 (because 0 is the default value of an int. If the variable that called the method is on type char but the user entered a bad value, the method returns two values: false and an empty character (because the default value of a char is empty). 

Here is another example of running the above program:

Enter a Value: 506GH
False: Value Entered = 0
Press any key to continue . . .

Notice that the compiler didn't produce (throw) an error (an exception).

The Minimum and Maximum Values of a Primitive Type

In Lesson 1, we saw that, when you declare a variable, the compiler reserves an amount of memory space preparing to store its value. As different variables have different requirements, some of them use less or more memory than others. When you declare a variable, the data type you specify allows the compiler to know how mush space would be needed to store the value of  that variable. There is a minimum and a maximum values that can be stored in the memory space reserved for a variable. Based on this, a value such as 224855 can be stored in space reserved for an int variable but it is beyond the space reserved for a Byte or a short.

To help you find out the minimum value that a data type can hold, each structure of a primitive type is equipped with a constant member named MinValue. In the same way, the maximum value that a data type can support is represented by a constant field named MaxValue. You can check these minimum and maximum with the following program:

using System;

class Program
{
    static int Main()
    {
        Console.WriteLine(
	"=======================================================================");
        Console.WriteLine("C# Type .NET Structure Minimum         Maximum");
        Console.WriteLine(
	"=======================================================================");
        Console.WriteLine("char    Char           {0}\t\t\t{1}",
				char.MinValue, char.MaxValue);
        Console.WriteLine(
	"-----------------------------------------------------------------------");
        Console.WriteLine("byte    Byte           {0}\t\t\t{1}",
				 byte.MinValue, byte.MaxValue);
        Console.WriteLine(
	"-----------------------------------------------------------------------");
        Console.WriteLine("sbyte   SByte          {0}\t\t\t{1}",
				 sbyte.MinValue, sbyte.MaxValue);
        Console.WriteLine(
	"-----------------------------------------------------------------------");
        Console.WriteLine("short   Int16          {0}\t\t\t{1}",
				 short.MinValue, short.MaxValue);
        Console.WriteLine(
	"-----------------------------------------------------------------------");
        Console.WriteLine("ushort  UInt16         {0}\t\t\t{1}",
				 UInt16.MinValue, UInt16.MaxValue);
        Console.WriteLine(
	"-----------------------------------------------------------------------");
        Console.WriteLine("int     Int32          {0}\t\t{1}",
				 int.MinValue, int.MaxValue);
        Console.WriteLine(
	"-----------------------------------------------------------------------");
        Console.WriteLine("uint    UInt32         {0}\t\t\t{1}",
				 UInt32.MinValue, UInt32.MaxValue);
        Console.WriteLine(
	"-----------------------------------------------------------------------");
        Console.WriteLine("long    Int64          {0}\t{1}",
				 long.MinValue, long.MaxValue);
        Console.WriteLine(
	"-----------------------------------------------------------------------");
        Console.WriteLine("uint64  UInt64         {0}\t\t\t{1}",
				 UInt64.MinValue, UInt64.MaxValue);
        Console.WriteLine(
	"-----------------------------------------------------------------------");
        Console.WriteLine("float   Single         {0}\t\t{1}",
				 float.MinValue, float.MaxValue);
        Console.WriteLine(
	"-----------------------------------------------------------------------");
        Console.WriteLine("double  Double         {0}\t{1}",|
				 double.MinValue, double.MaxValue);
        Console.WriteLine(
	"-----------------------------------------------------------------------");
        Console.WriteLine("decimal Decimal        {0} {1}",
				 decimal.MinValue, decimal.MaxValue);
        Console.WriteLine(
	"=============================================================");

        return 0;
    }
}

This would produce:

=======================================================================
C# Type .NET Structure Minimum                  Maximum
=======================================================================
char    Char                                    ?
-----------------------------------------------------------------------
byte    Byte           0                        255
-----------------------------------------------------------------------
sbyte   SByte          -128                     127
-----------------------------------------------------------------------
short   Int16          -32768                   32767
-----------------------------------------------------------------------
ushort  UInt16         0                        65535
-----------------------------------------------------------------------
int     Int32          -2147483648              2147483647
-----------------------------------------------------------------------
uint    UInt32         0                        4294967295
-----------------------------------------------------------------------
long    Int64          -9223372036854775808     9223372036854775807
-----------------------------------------------------------------------
uint64  UInt64         0                        18446744073709551615
-----------------------------------------------------------------------
float   Single         -3.402823E+38            3.402823E+38
-----------------------------------------------------------------------
double  Double         -1.79769313486232E+308   1.79769313486232E+308
-----------------------------------------------------------------------
decimal Decimal        -79228162514264337593543950335 79228162514264337593543950335
=============================================================
Press any key to continue . . .

Value Comparisons

One of the most common operations performed on variables consists of comparing their values: to find out whether they are equal or to know whether one is higher than the other. These operations can be performed using the Boolean operators we reviewed in Lesson 8. The Boolean operations are part of the C# language. To formally implement them, each structure of a data type is equipped with a method named CompareTo that is overloaded with two versions.

One of the implementations of the CompareTo() method compares a value or the value of a variable of the same type, with the variable that calls the method. This method takes one argument that is the same type as the variable that is calling it. The syntaxes of this method are:

byte
public int CompareTo(byte value)
sbyte
public int CompareTo(sbyte value)
short
public int CompareTo(short value)
ushort <=> UInt16
public int CompareTo(ushort value)
int <=> Int32
public int CompareTo(int value)
uint <=> UInt32
public int CompareTo(uint value)
long <=> Int64
public int CompareTo(long value)
unsigned long <=> uint64
public int CompareTo(ulong value)

The method returns an int value. For example, imagine you have two int variables named Variable1 and Variable2, you can call the CompareTo() method of the first variable to compare its value to that of the second variable. This would be done as in:

int result = Variable1.CompareTo(Variable2);

The end result would be as follows:

  • If the value of Variable1 is greater than the value of Variable2, the method returns 1
  • If the value of Variable1 is less than the value of Variable2, the method returns -1
  • If the values of both variables are equal, the method returns 0

Here is an example:

using System;

class Program
{
    static int Main()
    {
        int Variable1 = 248;
        int Variable2 = 72937;
        int result = Variable1.CompareTo(Variable2);
        Console.WriteLine("{0} compared to {1} produces {2}",
                          Variable1, Variable2, result);

        return 0;
    }
}

This would produce:

248 compared to 72937 produces -1
Press any key to continue . . .

Another version of the CompareTo() method allows you to compare the value of a variable with a variable whose type is not the same as the variable that called it. Since all types and classes of C# are based on object, this second version takes as argument an object object. The method return an int value. The syntax of this version is:

public int CompareTo(object value);

Notice that you can use the CompareTo() method to test for equality. Another method used to check the equality of two variables is the Equals() method. The Equals() method is overloaded in two versions and each takes one argument. The Equals() method returns a Boolean value. One of the versions of this method takes as argument a value of the same type as the variable that called it. The syntaxes of this version are:

byte
public bool Equals(byte obj)
sbyte
public bool Equals(sbyte obj)
short
public bool Equals(short obj)
ushort <=> UInt16
public bool Equals(ushort obj)
int <=> Int32
public bool Equals(int obj)
uint <=> UInt32
public bool Equals(uint obj)
long <=> Int64
public bool Equals(long obj)
unsigned long <=> uint64
public bool Equals(ulong obj)

The method compares the values of the variable that called it and the argument, as in

bool result = Variable1.Equals(Variable2);

The comparison is performed as follows:

  • If the value of the first variable is the same as that of the second variable, the method returns true
  • If the values of the variables are different, the method returns false

Here is an example:

using System;

class Program
{
    static int Main()
    {
        int  Variable1 = 1407;
        int  Variable2= 59266;
        bool result = value1.Equals(value2);
        Console.WriteLine("{0} = {1} produces {2}",
            Variable1, Variable2, result);

        return 0;
    }
}

This would produce:

1407 = 59266 produces False
Press any key to continue . . .

The other version of the Equals() method takes as argument an object value. The syntax of this version is:

public override bool Equals(object obj);

Here is an example:

using System;

class Program
{
    static int Main()
    {
        int    value1 = 824;
        object value2 = 824;
        bool result = value1.Equals(value2);
        Console.WriteLine("{0} = {1} produces {2}",
            value1, value2, result);

        return 0;
    }
}

This would produce:

824 = 824 produces True
Press any key to continue . . .

Built-In Structures: The Boolean Type

 

Introduction

As seen in previous lessons, the bool data type is used to represent a value considered as being true or false. In the .NET Framework, the bool data type is represented by the Boolean structure. The true value of a bool variable is represented by the TrueString field and the false value is represented by the FalseString member variable. In other words, when true (or false) is represented as a string, "true" (or "false"” is the same as TrueString (or FalseString).

Parsing a Boolean Variable

We saw in a Lesson 8 that you could retrieve the value of a Boolean variable from a user. To support this, the Boolean structure is equipped with a static method named Parse. The Boolean.Parse() method is declared as follows:

public static bool Parse(string value);

This method takes as argument a string. The argument must contain either the word True (case-insensitive) or the word False. If the argument is passed as "True", the method returns true. If the argument is "false", this method returns false. Here is an example:

using System;

class Program
{
    static int Main()
    {
        bool result = bool.Parse("TRUE");

        Console.WriteLine("Result: {0}", result);
        return 0;
    }
}

This would produce:

Result: True
Press any key to continue . . .

When calling the Boolean.Parse() method to retrieve the value of a Boolean variable, if the supplied value is "TRUE" or "FALSE", the compiler would process it. If the value is not valid, the program would produce an error. Here is an example:

using System;

class Program
{
    static int Main()
    {
        bool HouseHas3Bedrooms = bool.Parse("ItHas3Bedrooms");

        Console.WriteLine("House has 3 bedrooms: {0}", HouseHas3Bedrooms);
        return 0;
    }
}

To avoid the error, the Boolean structure provides the TryParse() method. Its syntax is:

public static bool TryParse(string value, out bool result);

The first argument is the value to be parsed. If that value is valid, the second argument holds the True or False value of the first. Here is an example:

using System;

class Program
{
    static int Main()
    {
        bool alt;
        bool HouseHas3Bedrooms = bool.TryParse("True", out alt);

        Console.WriteLine("House has 3 bedrooms: {0}", HouseHas3Bedrooms);
        Console.WriteLine("Alternate value: {0}", alt);
        return 0;
    }
}

This would produce:

House has 3 bedrooms: True
Alternate value: True
Press any key to continue . . .

Consider this other version of the same program:

using System;

class Program
{
    static int Main()
    {
        bool alt;
        bool HouseHas3Bedrooms = bool.TryParse("False", out alt);

        Console.WriteLine("House has 3 bedrooms: {0}", HouseHas3Bedrooms);
        Console.WriteLine("Alternate value: {0}", alt);
        return 0;
    }
}

This would produce:

House has 3 bedrooms: True
Alternate value: False
Press any key to continue . . .

Notice that the first argument returns True although it was passed as False. This means that, if the value of the first argument is valid, it is the second argument, not the first, that holds the result. If the first argument is not valid, the second argument returns a False value. Consider the following version of the program:

using System;

class Program
{
    static int Main()
    {
        bool alt;
        bool HouseHas3Bedrooms = bool.TryParse("Don't Know", out alt);

        Console.WriteLine("House has 3 bedrooms: {0}", HouseHas3Bedrooms);
        Console.WriteLine("Alternate value: {0}", alt);
        return 0;
    }
}

This would produce:

House has 3 bedrooms: False
Alternate value: False
Press any key to continue . . .

Comparisons of Boolean Variables

In C#, to compare the values of two Boolean variables for equality, you can use the equality operator "==". Here is an example:

using System;

class Program
{
    static int Main()
    {
        bool House1Has3Bedrooms = true;
        bool House2Has3Bedrooms = false;

        Console.WriteLine("House1 has 3 bedrooms: {0}", House1Has3Bedrooms);
        Console.WriteLine("House2 has 3 bedrooms: {0}", House2Has3Bedrooms);
        Console.WriteLine("House1 and House2 have the number of bedrooms: {0}",
            House1Has3Bedrooms == House2Has3Bedrooms);
        return 0;
    }
}

This would produce:

House1 has 3 bedrooms: True
House2 has 3 bedrooms: False
House1 and House2 have the number of bedrooms: False
Press any key to continue . . .

To support this comparison, the Boolean structure of the .NET Framework is equipped with the Equals() method. Its syntax is:

public bool Equals(bool obj);

This method takes one argument as the Boolean value or variable to be compared to the variable that called it. Here is an example of calling it:

using System;

class Program
{
    static int Main()
    {
        bool House1Has3Bedrooms = false;
        bool House2Has3Bedrooms = false;

        Console.WriteLine("House1 has 3 bedrooms: {0}", House1Has3Bedrooms);
        Console.WriteLine("House2 has 3 bedrooms: {0}", House2Has3Bedrooms);
        Console.WriteLine("House1 and House2 have the number of bedrooms: {0}",
            House1Has3Bedrooms.Equals(House2Has3Bedrooms));
        return 0;
    }
}

This would produce:

House1 has 3 bedrooms: False
House2 has 3 bedrooms: False
House1 and House2 have the number of bedrooms: True
Press any key to continue . . .

The Equals() method can easily be called by one Boolean variable that receives another Boolean variable as argument. If you don't know the exact type of value of the argument, you can still pass it an object value. To support this, the Equals() method has another version whose syntax is:

public override bool Equals(Object obj);

This version takes as argument a variable that is of any type.

Besides the equality, you can also compare two Boolean variables to know whether one is lower than the other. To support this, the Boolean structure is equipped with the CompareTo() method. Its syntax is:

public int CompareTo(bool value);

If the type of variable is not necessarily a Boolean type, you can pass it as an object value. To do this, you can use the other version of the CompareTo() method. Its syntax is:

public int CompareTo(Object obj);
 

Floating-Point Numbers

 

Introduction

As seen in Lesson 2, to support floating-point numbers, you can use the float, the double, or the decimal data types. The C# float data type originates from the Single structure of the .NET Framework. The double data type is based on the Double structure of the .NET Framework. The C# decimal data type is type-defined from the .NET Framework’s Decimal structure. To declare a floating-point variable, you can use one of these data types and initialize it.

When initializing a floating-point variable, you should make sure you assign it a value that can fit in the memory allocated for it. As mentioned for the integer data types, the minimum value that a float variable can hold is represented by the MinValue constant of the Single structure and the MinValue field of the Double. The maximum value that a float or a double variable can hold is named MaxValue.

After declaring and initializing a float or a double variable, it should hold an appropriate value. If you get the variable’s value some other way, at one time or another, you may not know what value is stored in the memory allocated for the variable. In fact, the variable may hold a value that is not a number. To check whether the variable is holding a value that is not a number, you can access its NaN constant. To do this, type the float or double data type, followed by the period operator, and followed by the NaN constant. Here is an example:

using System;

class Program
{
    static int Main()
    {
	double number = 0D;

	if( number == double.NaN )
	    Console.WriteLine("The value is not a number");
	return 0;
    }
}

Another technique you can use to check this characteristic is to IsNaN() method of either the Single or the Double structure.

Operations on Floating-Point Numbers

Using one integer and one floating-point number, or with two floating-point numbers, you can perform one of the routine arithmetic operations such as the addition, the subtraction, the multiplication, or the division. When it comes to the division and if performed on two constants, you can get a positive or a negative number. In highly precise calculations, you may have to deal with an approximate number whose exact value is not known. For example, the smallest positive number is called epsilon. In the Double and the Single structures, this constant is named Epsilon. For the single-precision type, the epsilon is equal to 1.445. For a double-precision type, the epsilon constant is equivalent to 4.94065645841247-324. As you can see, this number is extremely low.

When dealing with real numbers, some operations produce very little or very large numbers. In algebra, the smallest number is called negative infinity. In the .NET Framework, the negative infinity is represented by a constant named NegativeInfinity. To access this number, type either float or double, followed by a period operator, followed by the name of this constant. Here is an example:

using System;

class Program
{
    static int Main()
    {
	Console.WriteLine("Negative Infinity = {0}",
		double.NegativeInfinity);
	return 0;
    }
}

To find out if a variable holds a negative infinity value, you can call the IsNegativeInfinity() method from the variable. The syntaxes of this method are:

public static bool IsNegativeInfinity(float f);
public static bool IsNegativeInfinity(double d);

On the other extreme, the possible largest number is named positive infinity. This constant is represented in the .NET Framework by the PositiveInfinity value. To access this constant, type float or double, followed by the period, followed by the name of this constant. To find out if a variable’s value is a positive infinity, you can call its IsPositiveInfinity() method. The syntaxes of this method are:

public static bool IsPositiveInfinity(float f);
public static bool IsPositiveInfinity(double d);

To check whether the value of a variable is one of the infinities, you can call its IsInfinity() method. The syntaxes of this method are:

public static bool IsInfinity(float f);
public static bool IsInfinity(double d);

Comparison Operations

Because floating-point numbers can be approximate, you should be careful when comparing them, especially for equality. Consider the following examples:

using System;

class Program
{
    static int Main()
    {
	double number1 = 22.15D;
	double number2 = 22.15D;

	if( number1 == number2 )
	    Console.WriteLine("The values are equal");
	return 0;
    }
}

This would produce:

The values are equal
Press any key to continue . . .

For the sake of discussion, these values of these variables were limited to 2 decimal places. If they represented hourly salaries of employees, the comparison would be easily performed and can produce an exact result. If you want to apply more precision do the numbers, for example if the variables represent weight values, you would need more places on the right side of the decimal separator. Consider the following program:

using System;

class Program
{
    static int Main()
    {
	double number1 = 22.156D;
	double number2 = 22.157D;

    	if( number1 == number2 )
	    Console.WriteLine("The values are equal"); 
	else
	    Console.WriteLine("The values are NOT equal");
	return 0;
    }
}

This would produce:

The values are NOT equal
Press any key to continue . . .

This time, because of more precision, the variables don’t hold the same value.

Besides the equality, you can also compare floating-point variables to find out if one has a value lower than the other. To support such operations, the Single and the Double structures are equipped with a method named CompareTo. The rules of this method are functionally the same as those we reviewed for integers.

 

 

Previous Copyright © 2008-2016, FunctionX, Inc. Next