Basic C# Programming

C# is an object oriented language. Almost everything in C# must be part of a class and the main method is no exception. So under C# a minimal console program will look like this

class Prog
{
   static void Main()
    {
    }
}

As you all have noticed, the Main method is marked as static, this ensure that this method isn't dependent of the instanciation of the Prog class. You should also notice that this method is included in the Prog class thus making it a class method.
In the example above, the Main method takes no argument and returns nothing. Just like the main method in C/C++, the Main method has multiple overload possibilities. One of the most usefull may be

class Prog2
{
   static int Main(string[] args)
    {
       return 0;
    }
}

which is equivalent to the C/C++ function

int main(int argc, char** argv)
{
   return 0;
}

Including namespaces


Namespaces are a .NET feature used to logically group different classes.
You may access a class in a given namespace by specifying all the namespaces containing the class, just like this

class FullNS
{
   static void Main()
    {
        System.Console.WriteLine("Hello World!");
    }
}

In the previous example, we invoke the static WriteLine method which belongs to the Console class in the System namespace.
The other way to access a class in a given namespace is to tell C# that when you use a class, it should search for that class in some previously specified namespaces. This is done using the «using» directive.
The following example is similar to the previous one except that it use the «using» directive

using System;

class UsingNS
{
   static void Main()
    {
        Console.WriteLine("Hello World!");
    }
}

Inserting comments

 

Comments in C# are similar to those available in C/C++.
If your comment is on a single line you may use «».
If you want to write a multi-line comment, you must use «/*» to start your comment and «*/» to end it.

C# also introduce a new commenting scheme.
The «///» introduce the automatic code documentation. This type of comments generate an XML file that could be used for documentation.

class Test
{
   /// <summary>
   /// This is the summary of func()
   /// </summary>
   /// <param name="a">Explain parameter a of func</param>
   /// <param name="b">Explain parameter b of func</param>
   /// <returns>Explain the return value of func</returns>
   public int func(int a, string b)
    {
       return 0;
    }
}

Those comments accept a given set of tags:

Tag  Description
 Give you a way to indicate that the text within a description should be marked as code. Use code for multiple line block
code  Indicate that a multiple line block should be treated as code
example  Let you specify an example on how to use the method or other library member
exception  Let you specify which exception could be thrown
include  this tags allows you to refer to another file containing documentation. The intended use of this tag is to separate code from commenting 
list  Allows you to insert a list or a table in your code
para  This tags is only intended to structure your text. It only indicates that a new paragraph should be started
param  Let you comment a method parameter
paramref  Allows you to refer to a parameter inside your comment
permission  Let you document the access of a member
remarks  Allow you to add informations about a type, supplementing the information specify within summary
returns  Let you document the return value of a method
see  Let you specify a link from within a text
seealso  Let you specify the text that you want to appear in the "See also" section
summary  Let you describe a type or a type member
value  Let you describe a property

Assemblies

 

You can consider an assembly as a {deployment unit}.
In practice, an assembly can contain or refer to a number of types and physical files that are needed at runtime for successful execution.
Under .NET, there are two main types of assemblies:

  • Static assemblies
  • Dynamic assemblies

Static assemblies

Static assemblies may be subdivided in two other categories: Private assemblies and Shared assemblies.

Private assemblies are the default assemblies you're building when you compile your application. An application may use a private assembly by refering it using a static path or through an XML-based configuration file.

Shared assemblies are assemblies that may be used by any other applications. In order to create a shared assembly, you must add a version number, add a strong name by signing the assembly, and add it into the GAC (Global Assembly Cache).

Private Assemblies

An application using a private assembly has two options:

  • One-directory deployment
  • Multiple directory deployment

In the first case, the application and it's assembly are in the same folder.

If you want to use the second approach you must keep in mind how the CLR search for private assemblies:

  1. It looks for a .dll file whose name is the name of the assembly in the same directory as the application.
    2. If the first step failed, it looks for the dll in a subdirectory with the same name as the assembly name.
    3. Assuming that the CLR hasn't found the assembly dll, it will look for an .exe file whose name is the name of the assembly in the same directory as the application.
    4. If the CLR still doesn't find the executable, it will search for it in a subfolder whose name matches the assembly name.
    5. At this point the CLR throw an exception.

Shared assemblies

Shared assemblies must be registered in the GAC. In order to be able to register them, the following steps must be taken:

  1. Generate a private/public key pair using the sn.exe utility.
    2. Build the assembly with a version number and the generated key pair

Once built, the assembly may be register in the GAC using the {gacutil.exe} utility.

Following is a sample on how to make a shared assembly:

  1. On a console, generate a random key pair:
    sn -k originator.key
    2. Adding version number and key pair in the assembly:
    Modify the source code and add the following lines:

Under C#

using System.Reflection;
[assembly:AssemblyVersion("1.0.0.0")]
[assembly:AssemblyKeyFile("originator.key")]

Under C++

using namespace System::Reflection;
[assembly:AssemblyVersion("1.0.0.0")];
[assembly:AssemblyKeyFile("originator.key")];

Under VB

Imports System.Reflection;
<assembly:AssemblyVersion("1.0.0.0")>
<assembly:AssemblyKeyFile("originator.key")>

The AssemblyVersion string has the following scheme: Major.Minor.BuildNumber.Revision.

3. Compiling the assembly as usual

4. Register the assembly into the GAC
On a console, write the following line:
gacutil /i assembly.dll

That's all!
If you want to remove the assembly from the GAC, simply delete it from the GAC folder (%windir%\Assembly).

Dynamic assemblies

 

Those types of assemblies are created in memory using System.Reflection.Emit.

Native Images

 

A native image is an assembly compiled into native code in order to enhance it's speed execution.

Under MS .NET, the tool for generating a native image is ngen.exe
1 (Native image GENerator).

As each native image is stored in the GAC, in order to generate a native image correctly, the assembly must have a key pair and a version number (AssemblyKeyFile and AssemblyVersion respectively).

To generate a native image, simply type ngen filename or ngen assemblyname.

To remove a native image from the GAC, type ngen /delete assemblyname.

  1. ^ The ngen utility is currently not available under mono, but they're currently working on it. I expect it should run just like it's MS .NET counterpart.