Rapapaing Group

Introduction to C# for Programmers

By NullS

Introduction

It hasn't been more than a year since I discovered the true power of a new programming platform named .NET, and now I am literally addicted to it.

.NET was a platform created by Microsoft in 2002, with the release of their Microsoft Visual Studio .NET (also known as VS.NET 2002). .NET comes with a Common Language Runtime (from now on, CLR) which is similar to a Java Virtual Machine (JVM, also known as Java Runtime Environment or JRE) but it has made several improvements performance wise which I will talk about in another section.

The idea of .NET is to have as many options as possible to code the same thing, using the same libraries and resources and have all of them interoperate flawlessly, in other words, "write anywhere" (i.e., using your programming language of choice). For this reason they wrote a Common Language Specification (CLS) and Common Language Infrastructure (CLI), which are guidelines a language must follow to be able to run in a .NET environment

They wrote support for .NET for existing languages, such as Visual Basic which became Visual Basic .NET (VB.NET) and C++ which became C++ with Managed Extensions (Managed C++); they also wrote new languages, J#, which is based on Java and uses the same syntax, but runs on a .NET environment and has the .NET libraries, and C# which is a brand new language, based on C++, and adding tons of new features to really take advantage of the .NET environment.

Anyone else can write .NET support for any other language; I know Active State is working on .NET support for languages such as Perl.

C#, however, is my 'language of choice' for several reasons. For starters, it has a syntax I feel really comfortable with, C++ like syntax; also it was designed specially for .NET so it doesn't have any backwards compatibility issues and it can take advantage of the full potential of .NET (for example, J#, since it comes from Java, can't use operator overloading, properties, etc.).

This tutorial is aimed to people with basic programming knowledge; however, I'm sure it shouldn't be too hard to understand for a beginner anyway.

The Basics

What am I going to need?

Even though this tutorial will run on Windows, using the Microsoft Visual Studio 2005 software, you can get Visual C# Express for free to run it and it will be the same; if you're running on an Unix platform or simply don't want to use the Microsoft tools, you can always get Mono and MonoDevelop (for Linux) or SharpDevelop (for Windows).

I must emphasize that while I realise IDE's (Integrated Development Environments) such as SharpDevelop and MonoDevelop are very advanced and powerful, I have never used them and I will concentrate on the way things are done in Visual C# Express and Visual Studio 2005. I also know that as of the moment of the writing of this tutorial, SharpDevelop doesn't support .NET 2.0 specific features and MonoDevelop doesn't have a Form Designer.

Hello World!!

Hello world! If you have programmed before, I'm sure you've heard of hello world. It's the first program they ever teach you how to write in any language, and we're not going to be the exception, are we?

First open Visual Studio (or whatever your IDE is) and create a new Project. Make sure it says it's a C# Console Application. It should generate a source code file, copy paste the following code in it.

using System;

namespace CSConsoleIntroduction
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Console.Out.WriteLine("Hello World!");
            Console.Out.Read();
        }
    }
}

Now you're wondering what all that gibberish is.

The first line is a using statement; that means you're saying you're going to use the classes in the System namespace.

You're probably wondering "What the hell is a namespace? What are you talking about!?"

If so, I can help. Think of namespaces as categories - they categorise Objects, Classes, Interfaces and the rest of the fun stuff you can play with. The System namespace is always used because it includes the most basic classes. If you come from a Java context, you can think of a namespace as a "package".

The next line says whatever you're defining in the next code block, designated by { }, just like in C++ or Java, is going to be in the CSConsoleIntroduction namespace. You can actually skip this declaration, and everything will be defined with no namespace but it is not really recommended.

public class Program means you're defining a new class named Program, which is available to any other class anywhere else. You can skip the public modifier, but it'd be declared as internal which means it could only be accessed from that "assembly". It won't matter much for now, but later you'll see the problems with that.

The next line defines the Main method for the class Program. The Main method is the program's entry-point.

The next two lines are the actual program. The first of them writes the line "Hello World!" to the console, and the second waits for you to hit enter in your keyboard.

You can run it now (click the little play-like button or hit F5 in VS and VC#Express). Congratulations, you've written your first C# program.

Data Types

Every variable in your program has a Data Type. For example, a 32 bit integer number would be a System.Int32 (also identified by the C# Keyword int). There are many types included with .NET, some of them are considered basic Data Types by the language itself.

All Data Types in .NET inherit from the System.Object class (also known as the C# object basic data type), but even though all data types are 'objects' there are two kinds, Reference Types and Value Types.

Value Types

Most basic Data Types are, in fact, Value types. Value types reside in Stack, therefore they are created at the start of a Method, and automatically destroyed when it ends. They're only valid inside that method's scope.

When calling a method, if a Value Type variable is passed as an argument, a copy of it is created for the scope of the method (unless otherwise specified) leaving the original variable unmodified. This is called by value argument passing, hence the name.

All structs and most of the basic data types (numeric types, booleans, etc.) are Value Types. These automatically inherit from System.ValueType (which also inherits from System.Object, obviously).

Reference Types

Reference Types reside on the Managed Heap instead of in the stack. The Managed Heap is a memory area assigned and freed dynamically. The memory freeing process is the responsibility of a Garbage Collector. However, Garbage Collectors are not that efficient so you might want to be careful when assigning Memory.

When calling a method, if a Reference Type variable is passed as an argument, a reference to it is passed, not a copy, so whatever change is done to it in the method, is reflected outside of it. This is called by reference argument passing, hence the name.

All classes are Reference types.

List of Basic Data Types

C# type name.NET Framework typeSignedSize (Bytes)Value RangeValue Type / Reference Type
sbyteSystem.SbyteYes1[-128 .. 127]Value Type
byteSystem.ByteNo1[0 .. 255]Value Type
shortSystem.Int16Yes2[-32768 .. 32767]Value Type
ushortSystem.Uint16No2[0 .. 65535]Value Type
intSystem.Int32Yes4[-2147483648 .. 2147483647]Value Type
uintSystem.Uint32No4[0 .. 4294967295]Value Type
longSystem.Int64Yes8[-9223372036854775808 .. 9223372036854775807]Value Type
ulongSystem.Uint64No8[0 .. 18446744073709551615]Value Type
floatSystem.SingleYes4Approximately ±1.5 x 10-45 to ±3.4 x 1038with 7 significative figuresValue Type
doubleSystem.DoubleYes8Approximately ±5.0 x 10-324 to ±1.7 x 10308 with 15 or 16 significant figuresValue Type
decimalSystem.DecimalYes12Approximately ±1.0 x 10-28 to ±7.9 x 1028 with 28 or 29 significant figuresValue Type
charSystem.CharN/A2Any Unicode Character (16-Bit)Value Type
boolSystem.BooleanN/A1true, falseValue Type
stringSystem.StringN/ADepends on String SizeAny possible stringReference Type

Defining your own Data Types

Of course, it'd be pretty boring if you couldn't create your own data types, wouldn't it? Now I will explain what you can do to create a data type.

Fields

Fields represent the data itself. For example, if you want to write a class or structure which represents a person, its fields would be "name", "middleName", "surname", "birthdate", etc.

The syntax for defining fields is [modifiers] [type] [fieldName], for example:

private string name;
private string middleName;
private string surname;
private DateTime birthdate;

Methods

Methods are the action your class/struct/object can do, on itself or on something else. For example, in your Person class you might want to have, let's say, a "Marry" Method.

The syntax for defining methods is:

[modifiers] [type] [MethodName]([MethodArguments])
{
   [MethodCode]
}

If you would like to follow .NET's standards, make sure your methods use Camel Case.

Example

private Person spouse;

public void Marry(Person p)
{
   if(this.spouse != null)
      throw new Exception("You can't marry someone because you're already married, you two timing git!");
   // LOL Let's assume we're in a monogamous country/culture, just for the sake
   // of the joke and ease of the example
   if (ReferenceEquals(this, p))
      throw new Exception("Gee, you can marry yourself?");
   this.spouse = p;
   p.spouse = this;
}

public void Divorce()
{
   if(this.spouse == null)
      throw new Exception("You can't divorce because you're not even married!");
   this.spouse = null;
   p.spouse = null;
}

Properties

Object Oriented Programming dictates that you should encapsulate all data, and write accessors for it, these are known as Getters and Setters. While this is (in most cases) pure formality, because the Getters and Setters get and set the data directly, the C# and .NET code standards recommend to do so. However, instead of using Methods (which make the syntax unnatural and annoying), they recommend using properties, which actually are methods, but the usage syntax is more like public fields.

Defining properties

public string Name
{
   get
   {
      return name;
   }
   set
   {
      name = value;
   }
}

Notice how the property name is only different from the field name because of the casing. The coding standard says that we use Camel Case for Properties.

Using a Property

Assume p is an instance of the Person Class we're writing

//...

p.Name = "Miguel";
Console.Out.WriteLine(p.Name);

This would print the line Miguel to the console. The first code line automatically calls the Property setter, and the second, just using the property name calls the property Getter. While you can have much more complicated logic in these getters and setters, the syntax remains simple and natural.

Constructors

You always want to initialise your data to valid states for your program, don't you? That's what constructors are for, but I'm sure you knew that.

Default Constructor

It's the most basic constructor, it is always automatically created, but the generated version does nothing. If you don't want a default constructor you can always write an empty Default Constructor which is private, this can be useful if your Type needs input for data initialisation.

Syntax
[accessModifiers] [ClassName]()
{
   //Constructor code here
}
Example
public Person()
{ 
   this.name = "John";
   this.middleName = string.Empty;
   this.name = "Doe";
   this.birthdate = new DateTime(1986,2,24);
   this.spouse = null;
}

That is, if you want it to initialise to a John Doe, who's not married and has my birthdate. But since that's most likely NOT the case, I will change it to a private Default Constructor.

private Person()
{ 
}

Parametised Constructors

These will do the initialisation, but not to default values as the Default constructor would, it will initialise based on parameters passed by the programmer using this class/structure.

Syntax
[accessModifiers] [ClassName]([ConstructorParameters])
{
   //Constructor code here
}
Example
public Person(string name, string middleName, string surname, DateTime birthdate)
{
   this.spouse = null;
   this.name = name;
   this.middleName = middleName;
   this.surname = surname;
   this.birthdate = birthdate;
}

Events and Delegates

.NET is, as I call it, a nice mix between Object Oriented Programming and Event Oriented Programming. If you're knowledgeable in OOP Patterns, you probably have heard of the Observer Pattern, this could be considered something like that, but a lot more efficient and simple.

Delegates

Delegates are some kind of "Type-safe function pointers", if you come from C++ or C, you know very well what function pointers are.

Type safety for delegates include return type, number of arguments and argument types.

Delegates for events, in general, are of the form void DelegateName(object sender, System.EventArgs e). EventArgs is a class specially designed for this purpose, however you can always inherit from this class to specialise it. The sender object just identifies who triggered the call of that delegate. While such a form is not required, it is recommended that we abide by the .NET coding standards.

Syntax
[modifiers] delegate [returnType] [DelegateName]([arguments]);
Example

Class that inherits from EventArgs

public class MarriageStatusEventArgs:EventArgs
{
   private Person spouse; 

   public Person Spouse
   {
      get { return spouse; }
   }
   public MarriageStatusEventArgs(Person spouse)
   {
      this.spouse = spouse;
   }
   
}

Delegate definition

public delegate void MarriageStatusHandler(object sender, MarriageStatusEventArgs args);

It is also a standard that the word Handler is the suffix for any Delegate for an event.

Events

An event has a type, which MUST be a delegate, the type of method which can handle the event.

Defining an Event

So lets say I want to add two events, for when a person marries or divorces, so inside the class person I add these two lines.

public event MarriageStatusHandler Married;
public event MarriageStatusHandler Divorced;
Triggering an Event

For this I must modify the methods we created before.

public void Marry(Person p)
{
   if (this.spouse != null)
      throw new Exception("You can't marry someone because you're already married, you two timing git!");
   // LOL Let's assume we're in a monogamous country/culture, just for the sake
   // of the joke and ease of the example
   if (ReferenceEquals(this, p))   
      throw new Exception("Gee, you can marry yourself?");
   this.spouse = p;
   p.spouse = this;
   Married(this, new MarriageStatusEventArgs(p));
   Married(p, new MarriageStatusEventArgs(this));
} 
 
public void Divorce()
{
   if (this.spouse == null)
      throw new Exception("You can't divorce because you're not even married!");
   Person p = spouse;
   this.spouse = null;
   p.spouse = null;
   Divorced(this, new MarriageStatusEventArgs(p));
   Divorced(p, new MarriageStatusEventArgs(this));
}

When the code gets to the point of calling "Married" or "Divorced", it will call all handlers that registered for that event.

See how Married and Divorced are called, exactly the same as if they were normal methods of the form void Method(object, MarriageStatusHandler).

Registering to an Event

First of all we have to create the methods that handle the events, so, remember our Program class I wrote that hello world in? Let's add these methods/

public static void SomeoneMarried(object sender, MarriageStatusEventArgs e)
{
   Person p = (Person)sender;
   Console.Out.WriteLine("{0} {1} {2} has married {3} {4} {5}", p.Name,
       p.MiddleName, p.Surname, e.Spouse.Name, e.Spouse.MiddleName, e.Spouse.Surname);
}

public static void SomeoneDivorced(object sender, MarriageStatusEventArgs e)
{
   Person p = (Person)sender;
   Console.Out.WriteLine("{0} {1} {2} has divorced {3} {4} {5}", p.Name,
       p.MiddleName, p.Surname, e.Spouse.Name, e.Spouse.MiddleName, e.Spouse.Surname);
}

Wow, ready for action? Let's change our Main method

static void Main(string[] args)
{
   Person p = new Person("John", "", "Doe", new DateTime(1986, 02, 24));
   Person p2 = new Person("Fulanita", string.Empty, "De Tal", new DateTime(1985, 11, 21));
   p.Married += SomeoneMarried;
   p2.Married += SomeoneMarried;
   p.Divorced += new MarriageStatusHandler(SomeoneDivorced);
   p2.Divorced += new MarriageStatusHandler(SomeoneDivorced);
   p.Marry(p2);
   p2.Divorce();
   Console.Read();
}

So, explanation needed? Awww damn! I was hoping it wasn't needed.

First we create two persons, random persons, John Doe, and Fulanita De Tal.

Then we register the handler methods to the event for each person, using the += operator. You might say it's not very consistent, it's just me demostrating the two available syntaxes, using the new Delegate, and skipping it, both work.

Then I make them marry and divorce, the output in the console should be:

John  Doe has married Fulanita  De Tal
Fulanita  De Tal has married John  Doe
Fulanita  De Tal has divorced John  Doe
John  Doe has divorced Fulanita  De Tal
And congratulations, now you know how to use events!

Access modifiers

Access modifiers let you set basic "permissions" to .NET classes, interfaces, structures, methods, properties, etc.

You've already seen them used in this tutorial, however, they haven't been fully explained.

private

If applied to a member (nested class, method, property, constructor, field), it means only members of the same class/struct can access this member.

If applied to a class, struct or interface in a namespace, it means only classes or structs in the same namespace can use it.

public

Applied to anything, it means anyone can access it from anywhere.

protected

Only applicable to class members, it means any members of that class or any subclass (class that inherits from that one) can access it.

internal

Applicable to everything. It means that only classes/structs defined in the same assembly can use it. Assemblies are projects in Visual Studio, for example, a Class Library is an assembly, and a Windows Application that uses the Class Library is another assembly, therefore, an internal class/struct/interface/member defined in the Class Library can be accessed from anywhere in the class library, but NOT from the Windows application.

protected internal

Applicable to class members, means you can access the member from anywhere in the same assembly and from any subclass (disregarding whether it is in the same assembly or not).

Back to Articles

Contact the author by e-mail: mi-yanez [at] rapapaing [dot] com