A data type is a data representation which determines the following:
- How the values of a given type are stored in memory.
- The set of values that are stored.
- The set of operations that can be applied to all the values in that set.
A data type can also simply be referred to as a type.
Every variable normally has a data type that determines the kind of data that it can hold.
Categories for Data Types
Data types can categorized into two general categories:
- Built-in data types - These are data types predefined by the programming language.
- User-Defined data types - Custom data types created by the programmer.
Basic Measurement Units of data
Computers can handle as the smallest piece of data a bit.
A bit is a single binary digit of memory that can have either 0
or 1
.
A byte is a chunk of memory holding 8 bits
. A signed byte can hold from 0 (00000000 in binary) to 255 (11111111 in binary).
Some of the measurement units you may have heard of in computers with regards to space include:
Size | Equivalence |
---|---|
1 byte | 8 bits |
1 Kilobyte | 1024 bytes |
1 Megabyte | 1024 kilobytes |
1 Gigabyte | 1024 megabytes |
1 Terabyte | 1024 gigabytes |
Multiple bytes get grouped into words that contain 2, 4 or more bytes depending on the computer hardware.
Majority of computers these days use 4-byte(32-bit) words or 8-byte(64-bit) words.
C# also groups bytes in different ways to form data types with a greater logical meaning. E.g it uses 4 bytes to make an integer, a numeric data type that holdvalues between: −2,147,483,648 to 2,147,483,647
.
C# defines some keywords for fundamental data types. These can be used to represent:
- Local variables
- Class member variables.
- Return values for methods.
- Parameters.
Why Data Types?
C# is a strongly typed programming language.
This implies that in C# all operations are type checked at compile time by the compiler for type compatibility.
So if an illegal operation or assignment is detected, then an error is flaged immediately. The error has to be fixed before successful compilation.
Thus this compile-time type checking helps write safe code that is reliable.
However, obviously for us to talk about type checking then it means we need the types, or the data types.
Therefore all variables, expressions and values in C# have types. Having types also helps in determining the operations that can be done on given types.
In C# there are two general categories of data types:
- Value Types - Holds an actual value say for example an int value of
45
. Int in this case is a value type. - Reference Types - Holds a reference to the value, not the actual value. e.g is the class.
Value Types
Value types hold actual values, single values.
are also called simple types. Or primitive types.
Ther are 13 built in value types in C#. They provide the basis of C#'s type system.
The low level data elements onto which all C# programs rely on.
Using the new Operator with Intrinsic Data Types
All the intrinsic data types support a default constructor.
This allows the creation of variables using the new keyword. This will automatically set the variable to its default value as follows:
bool
:false
Integer
:0
Float
:0.0
char
: single empty characterBigInteger
:0
DateTime
:1/1/0001 12:00:00 AM
Object
:null
Example
int age= new int();
float salary=new float();
double d=new double();
bool isMarried=new bool();
DateTime date=new DateTime();
Pre-Defined Data Types
There are 16 predefined types in C#. These types can be divided into:
- Simple Types(13)
- Non-Simple Types(3)
All these predefined types are in lowercase characters.
The C# predefined types map directly to underlying .NET Base types.
The C# names are the aliases for these .NET base types.
Simple Types
The simple types include:
- Numeric Types(11). These include:
- Integers : Signed and Unsigned.
- Floating Point Numbers : Floats and Double.
- Decimal : High precision decimal type.
- Unicode Character type - Char.
- Boolean : bool represents true or false.
Name | Description | Range | Base Type | Default Value |
---|---|---|---|---|
sbyte | 8-bit signed integer | -128 to 127 | System.SByte | 0 |
byte | 8-bit unsigned integer | 0 to 255 | System.Byte | 0 |
short | 16-bit signed integer | -32,768 to32,767 | System.Int16 | 0 |
ushort | 16-biy unsigned integer | 0 to 65,535 | System.UInt16 | 0 |
int | 32-bit signed integer | -2,147,483,648 to 2,147,483,647 | System.Int32 | 0 |
uint | 32-bit unsigned integer | 0 to 4,294,967,295 | System.UInt32 | 0 |
long | 64-bit signed integer | -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 | System.Int64 | 0 |
ulong | 64-bit unsigned integer | 0 to 18,446,744,073,709,551,615 | System.UInt64 | 0 |
float | Single precision floating point | -1.5e45 to 3.4e38 | System.Single | 0.0f |
double | Double precision floating point | -5e324 to 1.7e308 | System.Double | 0.0d |
decimal | 28-bit significant digit precision decimal | ±1.0e28 to ±7.9e28 | System.Decimal | 0m |
bool | Boolean value | true, false | System.Boolean | false |
char | Unicode character | U+0000 to U+ffff | System.Char | x0000 |
Non-simple Types
The non-simple types include:
- string - a seqeunce of unicode characters.
- object - base type for creation of all other types.
- dynamic - usable when working with assemblies written in dynamic languages.
Name | Description | Base Type |
---|---|---|
object | base class for all types including simple types | System.Object |
string | sequence of zero or more Unicode characters | System.String |
dynamic | Type designed to be used with assemblies written in dynamic languages | No base type |
DataType Conversions
Programs are meant to manipulate data. And these data do exist in various types.
Sometimes you need to convert one data type to another.
C# provides us around six ways of converting data from one form to another:
- Implicit Conversions.
- Data Casting.
- Using the
as
Operator. - Data Parsing.
- Using
System.Convert
. - Using
System.BitConverter
.
1. Implicit Conversion
Implicit Conversions can be categorized into two
(a). Widening Conversions
Widening conversions occur when a variable of one data type is assigned to a variable of another data type whose maximum capacity is larger than former data type.
This involves storing a value in a variable that is guaranteed to to hold that value.
For example saving an int
value to a long
varaible.
EXAMPLE
using System;
namespace DataTypeConversions
{
class Program
{
static void Main()
{
int numOfPeople = 999;
long totalPopulation = numOfPeople;
Console.WriteLine("numOfPeople is of data type " + numOfPeople.GetType());
Console.WriteLine("totalPopulation is of data type "+totalPopulation.GetType());
Console.Read();
}
}
}
RESULT
numOfPeople is of data type System.Int32
totalPopulation is of data type System.Int64
You can see that numOfPeople
is of type System.Int32
, which is actually int
while totalPopulation
is of type System.Int64
which is the long
.
(b). Narrowing Conversions
In contrast in narrowing conversions the source value cannot fit into the destination variable.
For example if you have an int value and you want to convert it into a byte variable.
Well this cannot happen implicitly, even if the value itself is small enough say even 1 to fit into the destination variable.
Let's see an example:
int numOfPeople = 1;
byte enlightenedPeople = numOfPeople; //error won't compile
This cannot happen in C#. We cannot implicitly narrow say an int to a byte. To continue with the narrowing conversion you have to do it explicitly.