Topics on Numeric Types

The Minimum and Maximum Values of a Primitive Type

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 values with the following program:

<!DOCTYPE html>
<html>
<head>
<style>
.containment { width: 660px }
.sharp-col   { width: 80px; }
.net-col     { width: 80px; }
</style>
<title>Minimum/Maximum Values of Primitive Types</title>
</head>
<body>
<h2 style="text-align: center">Minimum/Maximum Values of Primitive Types</h2>

<div class="containment">
    <table style="width: 100%">
        <tr>
            <td class="sharp-col">C# Type</td>
            <td class="net-col">.NET Structure</td>
            <td>Minimum</td>
            <td>Maximum</td>
        </tr>
    </table>
    <hr />
    <table>
        <tr>
            <td class="sharp-col">byte</td>
            <td class="net-col">Byte</td>
            <td>@byte.MinValue</td>
            <td>@byte.MaxValue</td>
        </tr>
        <tr>
            <td>sbyte</td>
            <td>SByte</td>
            <td>@sbyte.MinValue</td>
            <td>@sbyte.MaxValue</td>
        </tr>
        <tr>
            <td>short</td>
            <td>Int16</td>
            <td>@short.MinValue</td>
            <td>@short.MaxValue</td>
        </tr>
        <tr>
            <td>ushort</td>
            <td>UInt16</td>
            <td>@ushort.MinValue</td>
            <td>@ushort.MaxValue</td>
        </tr>
        <tr>
            <td>int</td>
            <td>Int32</td>
            <td>@int.MinValue</td>
            <td>@int.MaxValue</td>
        </tr>
        <tr>
            <td>uint</td>
            <td>UInt32</td>
            <td>@uint.MinValue</td>
            <td>@uint.MaxValue</td>
        </tr>
        <tr>
            <td>long</td>
            <td>Int64</td>
            <td>@long.MinValue</td>
            <td>@long.MaxValue</td>
        </tr>
        <tr>
            <td>ulong</td>
            <td>UInt64</td>
            <td>@ulong.MinValue</td>
            <td>@ulong.MaxValue</td>
        </tr>
        <tr>
            <td>float</td>
            <td>Single</td>
            <td>@float.MinValue</td>
            <td>@float.MaxValue</td>
        </tr>
        <tr>
            <td>double</td>
            <td>Double</td>
            <td>@double.MinValue</td>
            <td>@double.MaxValue</td>
        </tr>
        <tr>
            <td>decimal</td>
            <td>Decimal</td>
            <td>@decimal.MinValue</td>
            <td>@decimal.MaxValue</td>
        </tr>
    </table>
</div>
</body>
</html>

This would produce:

The Minimum and Maximum Values of a Primitive Type

The Size of a Data Type

The C# language provides the unary sizeof operator that allows you to find out how much space a data type uses. To find out how much memory space a data type uses, type it between the parentheses of the sizeof operator. Here are examples:

<!DOCTYPE html>
<html>
<head>
<style>
.containment {
    width: 200px;
    margin: auto;
}
.data-type-col { width: 80px; }
</style>
<title>Sizes of Data Types</title>
</head>
<body>
    <div class="containment">
        <h2 style="text-align: center">Sizes of Types</h2>

        <table style="width: 100%">
            <tr>
                <td class="data-type-col">Data Type</td>
                <td>Memory Size</td>
            </tr>
        </table>
        <hr />
        <table style="width: 100%">
            <tr>
                <td class="data-type-col">bool</td>
                <td>@sizeof(bool) Byte</td>
            </tr>
            <tr>
                <td>byte</td>
                <td>@sizeof(byte) Byte</td>
            </tr>
            <tr>
                <td>sbyte</td>
                <td>@sizeof(sbyte) Byte</td>
            </tr>
            <tr>
                <td>short</td>
                <td>@sizeof(short) Bytes</td>
            </tr>
            <tr>
                <td>ushort</td>
                <td>@sizeof(ushort) Bytes</td>
            </tr>
            <tr>
                <td>int</td>
                <td>@sizeof(int) Bytes</td>
            </tr>
            <tr>
                <td>uint</td>
                <td>@sizeof(uint) Bytes</td>
            </tr>
            <tr>
                <td>long</td>
                <td>@sizeof(long) Bytes</td>
            </tr>
            <tr>
                <td>ulong</td>
                <td>@sizeof(ulong) Bytes</td>
            </tr>
            <tr>
                <td>float</td>
                <td>@sizeof(float) Bytes</td>
            </tr>
            <tr>
                <td>double</td>
                <td>@sizeof(double) Bytes</td>
            </tr>
            <tr>
                <td>decimal</td>
                <td>@sizeof(decimal) Bytes</td>
            </tr>
        </table>
    </div>
</body>
</html>

This would produce:

The Size of a Data Type

Unsafe Code

The C and C++ languages use pointers to refer to the area in memory where a value is located. C# highly avoids pointers and takes over memory management as opposed to letting the programmer worry about that. You can still use pointers in C# in extreme cases when you judge them necessary.

Because the C# compiler is in charge of managing the memory used by the values of an application, pointers are said to be unsafe. If you want to use a pointer in your application, you must precede the name of every method that uses unsafe code with the unsafe keyword. Here is an example:

class Exercise
{
    unsafe void DoSomthing()
    {
    	int Length = 224;
	int *Len = &Length;
    }
}

To compile the application, you must indicate that you are using unsafe code. To do that, use the /unsafe modifier. Here is an example:

csc /unsafe Exercise.cs

To apply this option in Microsoft Visual Studio, on the main menu, click Project -> Project Properties... In the Build section, click the Allow Unsafe Code check box:

Unsafe Code

The Values of an Enumeration

The Type of an Enumeration

As it was introduced in previous lessons, an enumeration is a list of members of a group where each member holds a constant integer. Here is an example of an enumeration:

public enum Alignment
{
    Left,
    Center,
    Right
}

The members of an enumeration can use values of one of the types of signed integers we reviewed. These include the byte, the short, the int, and the long integers (don't use their equivalent unsigned types. To indicate the type of integers you want the members to have, after the name of the enumeration, type a colon followed by the desired type. Here is an example:

ublic enum Alignment : byte
{
    Left,
    Center,
    Right
}

After doing this, each member is treated as if it were a static field of a class and it is of the type specified.

The Values of the Members of an Enumeration

Consider the following enumeration:

public enum HouseType
{
    Unknown,
    SingleFamily,
    TownHouse,
    Condominium
}

Each member of an enumeration holds a constant value. By default, the first member has a value of 0, the second has a value of 1, and so on. For example, in the above PropertyType enumeration, Unknown has a value of 0 while Townhouse has a value of 2 as the default values. If you don't want these values, you can specify the value of one member, each member, some members, or all members of the list. Suppose you want the Unknown member of our PropertyType enumeration to have a value of 5. To do this, use the assignment operator "=" to give the desired value. The enumerator would be:

public enum HouseType
{
    Unknown = 5,
    SingleFamily,
    TownHouse,
    Condominium
}

In this case, Unknown now would have a value of 5, SingleFamily would have a value of 6 because it follows a member whose value is 1 (thus 5 + 1 = 6). Townhouse would have a value of 7, and Condominium would have a value of 8. You can also assign a value to more than one member of an enumeration. Here is an example:

public class RealEstate
{
    enum HouseType
    {
    	Unknown = 3,
        SingleFamily = 12,
        TownHouse, Condominium = 8
    }
}

In this case, Townhouse would have a value of 13 because it follows SingleFamily that has a value of 12.

You can assign the same value to more than one member of an enumeration. Here is an example:

public enum HousePlan
{
    Unknown = 5,
    Cottage = 1,
    Ranch ,
    Colonial = 12,
    Country = 8,
    Bungalow,
    Contemporary = 12,
    Victorian
}

If you don't specify the data type of the enumeration, its default type is int. Otherwise, as we mentioned already, you can apply the integral type of your choice. If you do, the values you assign to the members must fit within the range allowed by that type.

Flagging an Enumeration

By default, each member of an enumeration is accessed one at a time. In fact, that's the common way enumerations are used in conditional statements. Some situations, such as properties of a class, allow the members of an enumeration to be combined to produce a common value. When creating an enumeration, to indicate that its members can be combined, apply an attribute named Flags (or FlagsAttribute to it. Here is an example:

[Flags]
public enum Alignment
{
    Left,
    Center,
    Right
}

You can still access each member by itself. Here is an example:

[Flags]
public enum Alignment
{
    Left,
    Center,
    Right
}

public class Exercise
{
    public Exercise()
    {
    	var something = Alignment.Center;
    }
}

In some case, depending on what you are trying to do, you may need to combine two or more members. To combine the members of an enumeration, you use the bitwise disjunction operator we reviewed in Lesson 5. You can assign the result to a variable. Here is an example:

[Flags]
public enum Alignment
{
    Left,
    Center,
    Right
}

public class Exercise
{
    public Exercise()
    {
    	var something = Alignment.Left | Alignment.Right;
    }
}

By the way, to make your code easy to read, you can put the expression in parentheses. Here is an example:

[Flags]
public enum Alignment
{
    Left,
    Center,
    Right
}

public class Exercise
{
    public Exercise()
    {
    	var positionOnAbortion = (Alignment.Left | Alignment.Center);
    }
}

Normally, after creating a flagged enumeration, you should (must) assign a value to each member. There are two rules you should (must) observe:

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 a structure named Boolean. The true value of a bool variable is represented by a field named TrueString. The false value is represented by a field named FalseString. 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

You can 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 or the word False (case-insensitive in both cases). If the argument is passed as "True", the method returns true. If the argument is "false", this method returns false.

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.

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.

Consider the following code:

@{
    bool alt;
    bool HouseHas3Bedrooms = bool.TryParse("False", out alt);
}

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:

@{
    bool alt;
    bool HouseHas3Bedrooms = bool.TryParse("Don't Know", out alt);
}

Comparing Primitive Values to Equality

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:

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);

Comparisons of Boolean Variables

In C#, to compare the values of two Boolean variables for equality, you can use the equality operator "==". 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.

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);

Practical LearningPractical Learning: Ending the Lesson


Previous Copyright © 2001-2019, FunctionX Next