In learning a new language, the first step is usually to learn basic
concepts such as variables, operators, types, expressions, etc.
Variables represent storage locations. Every variable has a type
that determines what values can be stored in the variable. C# is
a strongly type-safe language, and the C# compiler assures that
values stored in variables are always of the suitable type. In this
article, we will discuss the types in C#.
Types
The types of the C# language are divided into three categories:
Value types - include simple types (e.g., char, int, and float),
enum types, and struct types
Reference types - include class types, interface types, delegate
types, and array types
Pointer types - can be used only in unsafe code
Value types differ from reference types in that variables which
are value types directly contain their data, whereas variables of
the reference types store references to objects. With reference
types, it is possible for two variables to reference the same object,
and thus possible for operations on one variable to affect the object
referenced by the other variable. With value types, the variables
each have their own copy of the data, and it is not possible for
operations on one to affect the other.
using System;
class type
{
public int Value = 0;
}
class Test
{
static void Main() {
int val1
= 0;
int val2
= val1;
val2 = 123;
type ref1
= new type();
type ref2
= ref1;
ref2.Value
= 123;
Console.WriteLine("Values:
{0}, {1}", val1, val2);
Console.WriteLine("References:
{0}, {1}",
ref1.Value, ref2.Value);
}
}
The example above shows this difference. The output of the program
is:
Values: 0, 123 Refs: 123, 123
The assignment to the local variable val1 does not impact the local
variable val2 because both local variables are of a value type (the
type int) and each local variable of a value type has its own storage.
In contrast, the assignment ref2.Value = 123; affects the object
that both ref1 and ref2 reference.
Value Types
A variable representing an object of value type contains the object
itself. It does not contain a pointer to the object. The value types
of C# can be grouped as follows.
Simple Types
Integral Types - (sbyte, byte,
short, ushort, int, uint, long, ulong), bool type, char type,
Floating point types(float, double) and the decimal types.
They are all aliases of the .NET System Types.
The following table shows the integral types, their size,
and range.
Type
Size (in
bits)
Range
sbyte
8
-128 to 127
byte
8
0 to 255
short
16
-32768 to 32767
ushort
16
0 to 65535
int
32
147483648 to 2147483647
uint
32
0 to 4294967295
long
64
-9223372036854775808 to
9223372036854775807
ulong
64
0 to 18446744073709551615
char
16
0 to 65535
Boolean Types - the boolean
values are written to the console as a part of a sentence.
The "bool" type is simply either a true or false.
Its size is 1 bit.
Console.WriteLine("It
is {0} that this article is useful.", content);
Console.WriteLine("The
statement above is not {0}.", noContent);
}
}
When run, this program produces the following output:
It is True that this article is useful
The statement above is not False
Char Types - the char type is
used to represent Unicode characters. A variable of type char
represents a single 16-bit Unicode character. There are no
implicit conversions from char to other data types available.
That means treating a char variable just as another integral
data type is not possible.
Floating-Point Types - C# supports
two floating-point types
- float
- double
The float and double types are represented using the 32-bit
single-precision and 64-bit double precision respectively.
The decimal type is appropriate for calculations in which
rounding errors caused by floating point representations are
unacceptable. Common examples include financial calculations
such as tax computations and currency conversions. The decimal
type provides 28 significant digits.
Floating-point types are used when you need to perform operations
requiring fractional representations.
Type
Size (in
bits)
Precision
Range
float
32
7
digits
1.5 x 10^ -45
to 3.4 x 10^ 38
double
64
15-16 digits
5.0 x 10^ -324 to 1.7 x
10^ 308
decimal
128
28-29 digits
1.0 x 10^ -28 to 7.9 x
10^ 28
Struct Types
A struct type is a value type that can declare constructors, constants,
fields, methods, properties, indexers, operators, and nested types.
By using struct one can create lightweight objects. As with class
objects, no additional references are created in structs so we can
conserve memeory.
using System;
struct Data
{
public byte b1,b2;
}
class test
{
public static void Main()
{
Data myData;
myData.b1=111;
myData.b2=1;
Console.Write("{0}.{1}.",myData.b1,myData.b2);
}
}
Enumeration Types
An enumeration type is a distinct type with named constants. Every
enumeration type has an underlying type, which can be either byte,
short, int, or long. Enumeration types are defined through enumeration
declarations. An enum type declaration defines a type name for a
related group of symbolic constants. The body of an enum type declaration
defines zero or more enum members, which are the named constants
of the enum type. No two enum members can have the same name. An
enum declaration can not contain declarations of methods, properties,
events, operators, or types.
The associated value of an enum member is assigned either implicitly
or explicitly. If the declaration of the enum member has a constant-expression
initializer, the value of that constant expression, implicitly converted
to the underlying type of the enum, is the associated value of the
enum member.
If the declaration of the enum member has no initializer, its associated
value is set implicitly, as follows:
If the enum member is the first enum member declared in the
enum type, its associated value is zero
Otherwise, the associated value of the enum member is obtained
by increasing the associated value of the previous enum member
by one. This increased value must be within the range of values
that can be represented by the underlying type
using System;
enum Color
{
Red,
Green = 10,
Blue
}
class Test
{
static void Main()
{
Console.WriteLine(StringFromColor(Color.Red));
Console.WriteLine(StringFromColor(Color.Green));
Console.WriteLine(StringFromColor(Color.Blue));
}
static string StringFromColor(Color c)
{
switch (c)
{
case Color.Red:
return
String.Format("Red = {0}", (int) c);
case Color.Green:
return
String.Format("Green = {0}", (int) c);
case Color.Blue:
return
String.Format("Blue = {0}", (int) c);
default:
return
"Invalid color";
}
}
}
The code prints out the enum member names and their associated values.
The output is:
Red = 0
Blue = 10
Green = 11
For the following reasons:
the enum member Red is automatically assigned the value zero
(since it has no initializer and is the first enum member)
the enum member Blue is explicitly given the value 10
and the enum member Green is automatically assigned the value
one greater than the member that textually precedes it
Reference Types
A variable representing an object of Reference type contains a reference
or address of the actual data. Reference types are allocated on
the managed heap. Different reference types are:
The Object Type
The Class Type
Interfaces
Delegates
The String Type
Arrays
Object Types
The object class type is the ultimate base class of all other types.
Because it is the base class for all objects, you can assign values
of any type to it. Every type in C# directly or indirectly derives
from the object class type. It is not equivalent to void* as in
C++. The object type is used when a value type is boxed.
Class Types
A class type defines a data structure that contains data members
(constants, fields, and events), function members (methods, properties,
indexers, operators, constructors, and destructors), and nested
types. Class types support inheritance, a mechanism whereby derived
classes can extend and specialize base classes. Only single inheritance
is allowed by the .NET Framework. However, a class in C# can derive
from multiple interfaces.
String Types
The string type is a sealed class type that inherits directly from
the object type. Instances of the string class represent Unicode
character strings. Values of the string type can be written as string
literals. C# has base type string for manipulating string data.
Its usage is simple
string
author="arun ganesh";
We can even access a single character with the help of accessing
the indexer.
char first=author[0];
Interface Types
An interface declares a reference type that has abstract members
only. Only the signature exists and there is no implementation code
at all. An implementation of this is that we cannot instantiate
an interface; only an object that derives from the interface.
interface
Inter
{
void showInter();
}
As I said, we cannot instantiate an object from this definition,
but we can derive a class from it. However, that class must implement
the showinter abstract method. The main difference between interface
members and class members is that interface members do not have
an implementation.
class Ainter:Inter
{
public void showInter()
{
Console.WriteLine("IMPLEMENTATION");
}
}
Array Types
An array is a data structure that contains a number of variables
which are accessed through computed indices. The variables contained
in an array, also called the elements of the array, are all of the
same type, and this type is called the element type of the array.
using System;
class Array {
public static void Main() {
int[] Ints
= { 25, 9, 79 };
string[]
myStr = new string[4];
A delegate is a data structure that refers to a static method or
to an object instance and an instance method of that object. Delegates
encapsulate a method with a certain signature. The closest equivalent
of a delegate in C or C++ is a function pointer, but whereas a function
pointer can only reference static functions, a delegate can reference
both static and instance methods. In the latter case, the delegate
stores not only a reference to the method's entry point, but also
a reference to the object instance for which to invoke the method.
Unlike function pointers, delegates are object-oriented, type-safe,
and secure. Delegates are reference types that derive from a common
base class: System.Delegate. A delegate instance encapsulates a
method - a callable entity. For instance, methods have a callable
entity that consists of an instance and a method on the instance.
If you have a delegate instance and an appropriate set of arguments,
you can invoke the delegate with the arguments. An interesting and
useful property of a delegate is that it does not know or care about
the class of the object that it references. Any object will do;
all that matters is that the method's signature matches the delegate's.
This makes delegates perfectly suited for "anonymous"
invocation. This is a powerful capability.
There are three steps in defining and using delegates: declaration,
instantiation, and invocation. Delegates are declared using delegate
declaration syntax. A delegate that takes no arguments and returns
void can be declared with:
delegate
void SimpleDelegate();
A delegate instance can be instantiated using the new keyword, and
referencing either an instance or class method that conforms to
the signature specified by the delegate. Once a delegate has been
instantiated, it can be called using method call syntax.
class Test
{
static void A() {
System.Console.WriteLine("Test.A");
}
static void Main() {
SimpleDelegate d = new SimpleDelegate(A);
d();
}
}
A SimpleDelegate instance is created and then immediately invoked.
Of course, there is not much point in instantiating a delegate for
a method and then immediately calling via the delegate, as it would
be simpler to call the method directly. Delegates show their usefulness
when their anonymity is used. For example, we could define a MultiCall
method that can repeatedly call a SimpleDelegate.
void MultiCall(SimpleDelegate
d, int count)
{
for (int i = 0; i < count;
i++)
{
d();
}
}
Summary
C# is a strongly type-safe programming language. Thus, all operations
on variable are performed with consideration of what the variable's
type is. This article concentrated on a lot of important information
about the C# types.
About the Author
G. Gnana Arun Ganesh is the Administrator and the Founder of Arun
Micro Systems. He has been programming in C++, Visual Basic,
COM, Java and Microsoft Technologies for 4 years. He has written
over 50 articles on .NET published on websites such as CsharpCorner,
CsharpHelp, MSDNAA, Code Project, Developersdex, eXPerienceDotNet,
411asp.net, ProgrammersHeaven, VB-World, and Devguru etc. He has
performed numerous technical reviews for Prentice Hall, Prentice
Hall PTR and Sams. He has also created real time projects and Web
Services. Currently, he is reviewing a book on .NET Security and
has put forward a couple of proposals on .NET using C#.