Sunday, 8 July 2012

Introducing Data Types in C#


Integral Types:
DataType
Size
. Net (CTS)
Comments
byte
1
System.Byte
0 - 255 It is Unsigned
sbyte
1
System.SByte
-128 to 127 – Signed
short
2
System.Int16

ushort
2
System.UInt16

int
4
System.Int32
Range for
n – bits signed numbers: -2n-1 to 2n-1 - 1
n-bits unsigned numbers = 0 to 2n - 1
uint
4
System.Unt32
long
8
System.Int64
ulong
8
System.UInt64

Floating Types (the position of decimal point is not fixed):
float
4
System.Single
Has up to 8 digits after decimal
double
8
System.Double
Has up to 16 digits after decimal

decimal*
16
System.Decimal
Has 28 digits after decimal and its fixed
Even though the decimal data type as decimal point it’s not floating because the number of digits after decimal are fixed i.e. 28 digits. It’s ideal for representing calculations which should have least amount of data loss
Other DataTypes:
char
2
System.Char
Uses Unicode Charset and thus supports multiple languages
string **

Systring.String
Uses Unicode Charset
bool
1
System.Boolean
True / False
object **

System.Object
Generic Datatype
**All the above data types are Value Types except String and Object, which are Reference

Why Datatypes?

Ø  It’s based on the data type only the size of variable and the format in which it is stored in memory is decided.
Ø  Based on the data type only the compiler is going to validate the expressions for their validity. For example “a”/3 is compilation error because string cannot be divided by integer.
Ø  Even runtime evaluates the expression based on data types only. For example 1+2 = 3 where as “1” + “2” = “12”.
Ø  Always properly choose datatypes because it can even affect the performance of the application. For example: Floating point mathematical operations are slow in comparison to integral operations.
Ø  Local Variable: All parameters of the method and variables which are declared in scope of a method.

Memory Allocation:

Memory of every application where the variables reside is divided into three main parts.
1.       Global Memory: Used by all global variables. These variables are allocated memory when the application begins and will remain in memory throughout the life of the application. Developer is not required to do any memory management for this section.
2.       Stack Memory: Used by local variables and parameters of a method. When a method is invoked a stack of memory is allocated to the method and the same is cleared when the method returns. So this is also self-managed.
3.       Heap Memory: All dynamic/runtime memory requirements of an application are fulfilled from the heap memory. After allocating some memory from heap to a variable, once its job is completed the memory allocated to the variable must be returned back to heap so that the same can be reused for another variable. In programming languages like “C”, when malloc or calloc is used for pointers, memory is allocated from the heap and when free is used it is released from the heap. Heap memory has to be managed by programmer of “C” and if not properly managed it leads to issues like Dangling Pointers and Memory Leakage.

Value Types and Reference Types

a.       All datatypes in MS.NET are categorized as either Value Types or Reference Types.
b.      Value Types directly hold the value i.e. variable itself holds the value itself.
c.       Reference Types hold the reference to the value on HEAP i.e. variable holds reference to the value and value is in heap.
d.      All Basic Types, Structures & Enum are value types.
e.      String, Object, Class, Arrays, Delegates are categories as Reference types.
f.        Value types are allocated memory based on the scope of the variable, If its Global Variable its allocated memory in Global Memory Area, if its Local Variable or Parameter its allocated memory on stack and if it’s a member of an object its allocated memory on Heap.

Variable Declaration Syntax

int a,b;
int a=10, b=20;
·           A local variable declared must be explicitly initialized before used in an expression otherwise gives an compilation error.
·           A variable declared in a block is local to the block in which it is declared.
·           A variable declared in outer block cannot be re-declared in the inner block.

Casting:

Converting data from one form to another form.
If RHS expression and LHS variable are not of same data type then casting is required.
Casting can be implicit casting or explicit casting.
Implicit Casting: If every possible value of RHS expression is valid for a variable on LHS variable.
Explicit Casting: If an RHS expression is assigned to LHS and if there is a possibility of data loss then explicit casting is needed.

Program to caste integer to byte
using System;
class Program
{
    public static void Main()
    {
        int n = 256;
        n = b //Implicit casting
        b = n //Invalid
        b = (byte) n //Explicit casting
        byte b;
        byte b1, b2, b3;
        b1 = b2 = 10;
        b1 = b2 + b3; //Compilation Error
        //if  either byte, short or char variables are used in an expression they are automatically raised to the rank of int.
        b1 = (byte)(b2 + b3);
   }
}
Code: 3.1
C#


·         Casting is done based on range and not based on size of the data type.
·         Byte can be implicitly assigned to any data type.
·         Short can be implicitly assigned to all data types except Byte and So on…

Code snippet for handling overflow checks
unchecked //Overflow checks are not done…
{
    b = (byte) n;
    Console.WriteLine(b);
}
checked //Overflow checks are done…
{
   b = (byte) n;
   Console.WriteLine(b);
}

To Enable / Disable Overflow checks:
Project à Properties à Compile à Scroll and Click on Advanced Compile Options à Check Integer Overflow Checks

Note: You cannot use the checked and unchecked keywords to control floating point (non-integer) arithmetic. The checked and unchecked keywords control only integer arithmetic. Floating point arithmetic never throws OverflowException.
Converting float & decimal datatypes
        double dbl = 0.6D; //0.6
        float f = 0.6F;
        decimal dec = 0.6M;
//long to float
        long lng = 10L;
        f = lng; //because range of long is smaller than float
        lng = (long) f;
//float and decimal requires casting
        dec = 10; //Integer to decimal
        //f = dec; //Invalid
        //dec = f; //Invalid
        f = (float) dec;
        dec = (decimal) f;
//“decimal” should be explicitly casted to every other type if required.

Boxing is the term used to describe the transformation from Value Type to reference type (Object). The runtime creates a temporary reference-type box for the object on the heap.
UnBoxing is the term used to describe the transformation from reference type (Object) to value type.  We use the term cast here, as this has to be done explicitly.
        object obj = n; //Boxing
        n = (int) obj; //Unboxing
1            When a value is boxed to an object type, the object type variable cannot be used in any mathematical operations.
2            When the value of object type variable cannot be assigned to variable on LHS, an Exception of type InvalidCastException is thrown.
3            Excessive usage of Object data type makes the language “Loosely Typed” and also because of frequent casting requirement while Boxing and Unboxing performance is also degraded.
4            Boxing / Unboxing should be used only in situations where until runtime we don’t know the type of data we are going to deal with.  

Casting between other datatypes
      //int to char.
        n = c;
        /*c = n; invalid */
        c = (char) n;
       //bool – int - anydatatype explicit or implicit casting is not allowed either direction
       //string to int
        s = "100";
        n = (int) s; //Invalid – String cannot be casted
        n = int.Parse(s); //if failes throws, FormatException
        bool bln = int.TryParse(s, out n);
        //n = (int) s; //Direct casting of string to int is not allowed.
        //int to string
        s = n.ToString();
        //s = (string) n //Casting of int to string is not allowed

Program to Print the Char equivalent of the Ascii value read from the keyboard
using System;
class Program
{
    static void Main(string[] args)
    {
        string str;
        str = Console.ReadLine();
        int n = 100;
        if (int.TryParse(str, out n))
            Console.WriteLine((char)n);
        else
            Console.WriteLine("Invalid number");
    }
}
Code: 3.2
C#

 

const double PI = 3.14;
PI = 10; 'Invalid – The value of constant cannot be changed.
Ø  It is recommended to have the name of constant always in upper case.
Ø  Constants increase readability of code.
Ø  When the code is compiled all the occurrences of constant in code is replaced with the value of that constant.
Ø  If a constant value has to be changed during development, it can be changed at one place i.e. in declaration and this will be reflected everywhere the constant is used in the application.

Enum Declaration
enum WeekDay : int //WeekDay is subtype of int
{
    Sun=1, Mon, Tues, Wed=5, Thus, Fri, Sat
}
Enum can be subtype of any integral type only.

In Main
using System;
class Program
{
    static void Main(string[] args)
    {
        n = 2; //n is int
        WeekDay wd = WeekDay.Sat;
        wd = (WeekDay) n; //Explicit
        //n = wd; //Invalid
        n = (int) wd; //Explicit
     }
}
Ø  Enums can be subtype of integral types only
Ø  Enum is a collection of constants and can be used for more readability in code.
Ø  If an invalid integer is casted to enum variable, it doesn’t throw an exception.
Ø  Default value of the first Enum member is “0”.
Ø  Enum is a data type by itself and can be declared outside the Class or Module.

Strings in .net are called as Immutable (not modifiable) objects. They are Reference Types and hence are allocated memory on heap.
string s;
s = "Deccan" //Creates a new string on the heap.
s = s & "soft" //Creates another string on the heap by value “Deccansoft” and the old string “Deccan” is ready for garbage collection.
  1. Because of the above behavior it is not recommended that the string data type is used for those variables which need frequent modifications in their value.
  2. Instead we should use the class called as “System.Text.StringBuilder” for those operations which need very frequent modification to the string. It allocates memory to the string in blocks and the capacity is automatically managed.
Program to demonstrate the use of String Builder – Example 1
class Program
{
    static void Main(string[] args)
    {
        string str;
        System.Text.StringBuilder sb = new System.Text.StringBuilder(10);
        Console.WriteLine(sb.Capacity);//output=10
        for (int i = 0; i < 100; i++)
        {
            sb.Append("A");
            Console.WriteLine(sb.Capacity + " " + sb.Length);
        }
        str = sb.ToString();
    }
}

3 comments:

  1. Fabulous Job Sandeep Sir......
    Thanks a lot

    ReplyDelete
  2. Really helpful..Thanks for posting the article sir...Looking forward to see many more articles...!!

    TFS...!!!

    ReplyDelete