Click Here to Install Silverlight*
IndiaChange|All Microsoft Sites
MSDN
|Developer Centers|Library|Downloads|How To Buy|Subscribers|My MSDN
 
C# and Its Types
By G. Gnana Arun Ganesh
 
Article Posted: September 13, 2002
 
INTRODUCTION
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.

using System;

class Booleans {

    public static void Main() {
        bool content = true;
        bool noContent = false;

        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];

         Console.WriteLine("Ints[0]: {0}, Ints[1]: {1},
            Ints[2]: {2}",Ints[0],Ints[1],
            Ints[2]);

         myStr[0] = "gnana arun ganesh";
         myStr[1] = "gnanavel";
         myStr[2] = "vadi";
         myStr[3] = "saru";

         Console.WriteLine("myStr[0]: {0}, myStr[1]: {1},
                            myStr[2]:{2},myStr[3]: {3}",
                            myStr[0], myStr[1], myStr[2]),
                            mystr[3]);

         }
}

Delegate Types

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#.
 

©2009 Microsoft Corporation. All rights reserved. Contact Us |Terms of Use |Trademarks |Privacy Statement
Microsoft