This blog is moved to
http://amalhashim.wordpress.com

Sunday, April 4, 2010

.Net Framework | Value Types

Value type holds data in the variable. They are stored in “Stack”. Because of this the performance is good and causes minimal overhead. Mainly there are three value types

1. In built

2. User defined(structs)

3. Enums

All the above are derived from System.Value

Type Bytes Occupied Range
System.SByte 1 -128 to 127
System.Byte 1 0 to 255
System.Int16 2 -32768 to 32767
System.Int32 4 -2147483648 to 2147483647
System.UInt32 4 0 to 4294967295
System.Int64 8 -9223372036854775808 to 9223372036854775807
System.Single 4 –3.402823E+38 to 3.402823E+38
System.Double 8 -1.79769319486232E+308 to 1.79769319486232E+308
System.Decimal 16 -79228162514264337593543950335 to 79228162514264337593543950335
System.Char 2  
System.Boolean 4  
System.DateTime 8 1/1/0001 12:00:00 AM to 12/31/9999 11:59:59 PM
System.Boolean 4 True/False
System.IntPtr Platform Dependent  

Nullable Types

In some scenarios we might need to store the value null in the basic types. For doing that we can make the type nullable as shown below

bool? isValid = null;
//or
Nullable<bool> isSelected = null;


Structures or User Defined Types


Struct as mentioned is also a value type and is stored on the stack. Struct resembles class, but have several differences. Structures are composite types. They form a meaningful  data. The most common example give for structures is the Point type available in System.Drawing namespace. Each point can be represented using x and y coordinate and hence a structure can be formed as


struct Point
{
public UInt32 X;
public UInt32 Y;
}



I have enhanced the Point structure as shown below



using System;
using System.Text;

namespace ConsoleApplication2
{
struct Point
{
public UInt32 X;
public UInt32 Y;

public Point(uint x, uint y)
{
this.X = x;
this.Y = y;
}

public static Point operator +(Point p1, Point p2)
{
Point newPoint = new Point(p1.X + p2.X, p1.Y + p2.Y);

return newPoint;
}

public static Point operator -(Point p1, Point p2)
{
Point newPoint = new Point(p1.X + p2.X, p1.Y + p2.Y);

return newPoint;
}

public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append("The current point has X = ").Append(this.X.ToString())
.Append(" and Y = ").Append(this.Y.ToString());
return sb.ToString();
}
}

class Program
{
static void Main(string[] args)
{
Point p1 = new Point(10, 20);
Point p2 = new Point(20, 30);

p1 += p2;

Console.WriteLine(p1);

}

}
}

As you can see the structure has a parameterized constructor and can have methods. It also has overloaded operators.


Note: We can’t use default constructors in Structure. Default constructor is used by the framework to initialize the fields in structure.


Note: Always make use of a structure only if the entire data in it constitute less than 16 bytes.


Enumerations or Enum


Enums are grouped constants. They are introduced mainly to make the code readable.


Lets extend the above application by adding an Enum Direction. Based on the direction the point will be moved.


using System;
using System.Text;

namespace ConsoleApplication2
{
struct Point
{
public UInt32 X;
public UInt32 Y;

public Point(uint x, uint y)
{
this.X = x;
this.Y = y;
}

public static Point operator +(Point p1, Point p2)
{
Point newPoint = new Point(p1.X + p2.X, p1.Y + p2.Y);

return newPoint;
}

public static Point operator -(Point p1, Point p2)
{
Point newPoint = new Point(p1.X + p2.X, p1.Y + p2.Y);

return newPoint;
}

public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append("The current point has X = ").Append(this.X.ToString())
.Append(" and Y = ").Append(this.Y.ToString());
return sb.ToString();
}

public void Move(Direction d)
{
switch (d)
{
case Direction.Up:
if (this.X > 0)
this.X--;
break;
case Direction.Down:
if (this.X < 1000)
this.X++;
break;
case Direction.Left:
if (this.Y > 0)
this.Y--;
break;
case Direction.Right:
if (this.Y < 1000)
this.Y++;
break;
default:
break;
}
}
}

enum Direction
{
Up,
Down,
Left,
Right
}

class Program
{
static void Main(string[] args)
{
Point p1 = new Point(0, 0);
Console.WriteLine(p1);
p1.Move(Direction.Left);
Console.WriteLine(p1);
p1.Move(Direction.Down);
Console.WriteLine(p1);
p1.Move(Direction.Left);
Console.WriteLine(p1);
p1.Move(Direction.Right);
Console.WriteLine(p1);
}

}
}

2 comments:

Sen Thomas said...

I didnt get the point "Note: Always make use of a structure only if the entire data in it constitute less than 16 bytes." Can you please explain it.
It would be appreciable if you give one real time scinario where Class should avoid and Structure should use.
The Zen of dotnet programming world

A.m.a.L Hashim said...

@Sen:

If a structure is not larger than 16 bytes, it can be copied with a few simple processor instructions. If it's larger, a loop is used to copy the structure. As long as the structure is not larger than 16 bytes, the processor has to do about the same work when copying the structure as when copying a reference. If the structure is larger, you lose the performance benefit of having s structure, and you should generally make it a class instead.

Real world scenarios...hmmmm....simple and only one rule of thumb, if size of the object is less than 16 go for struct