December 6, 2013

Data Types, Constants and Enumerations

In the last post, we discussed about variables, conditional statements and switch statements. I also mentioned that we shall continue discussion on variables.

So in this post, we shall discuss more on variables, for example data types, constants and enumerators.

By now we know how to declare a variable. You have to specify the data type followed by a variable name. C# provides a large and useful collection of data types. There are primitive data types.
C# Data Types
Image courtesy: MSDN Library

Objects: Almost everything in C# is an object. This is really cool and neat. All the primitive data types that we have seen above are treated as objects in C#. Note that we shall discuss about objects as a concept in later posts.
As you can see in the image above, the column .NET class gives the class name to which these data types are related to. Interestingly, these classes are directly derived from the base class System.Object. Take a look at the following code snippet.
int i;
int j = new int();
//functionally equivalent

Essentially C# interprets both the lines in the same way. Functionally they are equivalent. But there are some added advantage with the object thing that we declare on line 2. We can use the methods that .NET framework provides for the objects.
j.GetType();   //returns System.Int32 the type of the object
j.ToString();  //returns a string
j.Equals(k);   //returns true/false if two objects are equal


This is one way to utilize the power of objects. There's much more. We shall learn about functions in the days to come, but we can discuss a little for the sake of understanding the purpose of objects.
There is a is operator in C#. The is operator returns a boolean type. It returns true if a given object is certain type.
void MyFunction(object obj)
{
 if(obj is int)
 {
  int k = (int)obj;
  //do something with k
 }
 else if(obj is string)
 {
  string s = (string)obj;
  //do something with s
 }
}

The statements on line 5 and 10 are called unboxing process, converting a reference type to its value type. You can see that MyFunction takes an object type as parameter. Then inside the body, you can decide if the object is of certain type. In this case, you just checked if it is an integer or a string type.

The reverse of unboxing is called boxing. Here is an example snippet directly from the MSDN library.
int i = 123;      // a value type 
object o = i;     // boxing 
int j = (int)o;  // unboxing

Constants: Constants are useful constructs in C# and makes your program easier to understand. Lets take an example.
if(i >= 100)
{
 //do something
}

So what is 100? What does that mean? Will it change in future? Surely someone debugging your code in future will ask these questions. This is certainly a bad practice. A general solution to this problem can be
const int HIGH_ORDER = 100;
if(i >= HIGH_ORDER)
{
 //customer asked for more than 100 units
}

The constant makes it clear that some customer asked for atleas 100 units of your goods. Obviously that is a huge order to sell.

Enumerations: Enumerations, or enums, are used to group named constants similar to how they are used in C, C++ or Java. Continuing the above example, if we think of an imaginary inventory store where we keep track of the order of goods that a customer asked for, we can do it in the following way.
public enum GoodsOrder
{
 VeryLow = 10,   //note that each constant ends with a comma ,
 Low = 30,
 Medium = 60,
 High = 100
}

Individually, each of them are constants. But for the sake of our code clarity, we grouped them under an enum and we named it GoodsOrder. So how do we use them? Let's complete the full code.
using System;

namespace Spells
{
    class Program
    {
        public enum GoodsOrder
        {
            VeryLow = 10,   //note that each constant ends with a comma ,
            Low = 30,
            Medium = 60,
            High = 100
        }
        static void Main(string[] args)
        {
            int c_order = 80;   //change the values to see different output

            if (c_order < (int)GoodsOrder.VeryLow)
            {
                Console.WriteLine("Sorry we do not sell below 10 units");
            }
            else if(c_order >= (int)GoodsOrder.VeryLow && c_order < (int)GoodsOrder.Low)
            {
                Console.WriteLine("Each unit will be charged 100 Taka");
            }
            else if (c_order >= (int)GoodsOrder.Low && c_order < (int)GoodsOrder.Medium)
            {
                Console.WriteLine("Each unit will be charged 97 Taka");
                //the customer is taking quite a lot, so you give him a reduced price
            }
            else if (c_order >= (int)GoodsOrder.Medium && c_order < (int)GoodsOrder.High)
            {
                Console.WriteLine("Each unit will be charged 95 Taka");
            }
            else if (c_order >= (int)GoodsOrder.High)
            {
                Console.WriteLine("Each unit will be charged 90 Taka");
                //thats business
            }
            Console.ReadLine();  //this will just keep the console visible
        }
    }
}


Just copy and paste this code and hit F5.

The last thing you need to know, enumerations start by default at 0 and if you do not provide values by yourself, the compiler will assume values starting from 0 and will assign values incrementally to the rest.
public enum GoodsOrder
{
 VeryLow,  //defaults to 0
 Low,   //defaults to 1
 Medium,   //defaults to 2 
 High      //defaults to 3
}

Enumeration is by default integer type. You can assign another type if you think you can optimize the spaces that these constants take in the memory.
public enum GoodsOrder : byte
{
 VeryLow,  //defaults to 0
 Low,   //defaults to 1
 Medium,   //defaults to 2 
 High      //defaults to 3
}

If you declare byte type, make sure that the values range between 0 to 256. You can specify other types like sbyte, short, ushort, int, long, uint, ulong etc.

I hope this post makes good use to your coding experience.

No comments:

Post a Comment