C# Tutorial Lesson 18: Using the C# Compiler

As we have noted earlier, C# classes are compiled in the first place to the Common Language Runtime Intermediate Language (IL). And as shown in lesson 3, one compiles these classes using the command-line command

csc file.cs

Where the required classes are held in more than one file, these should be listed, separated by spaces, as in:

csc file1.cs file2.cs

Broadly speaking, one can compile C# classes into either executable files or dynamic link library - DLL - files (see the /t switch in the table below). An executable file is one that can contains a runnable program (note that in the classes compiled to an executable file, there should be only one 'Main' method). A .NET dynamic link library just collects together an assembly of classes, which can then be instantiated and utilised by programs in the course of their running.

If your classes reference external classes, the C# compiler must be able to locate them. By default, the compiler only looks within the 'mscorlib.dll' assembly, which supports the basic Common Language Runtime functions. To point the compiler in the direction of other classes, use the /r switch described in the table below (note that there is no equivalent to the Java approach of setting the environment variable CLASSPATH). To find the appropriate assembly for .NET framework classes, consult their documentation.

The following gives a list of the compiler switches we have found useful, but we would advise you to look further at the .NET documentation to see which other ones are available.

Compiler SwitchDescription
/r:dll or /reference:dll
eg.
/r:System.xml.dll, System.Net.dll
This tells the C# compiler to include one or more of the .NET framework DLLs. As the standard library namespaces are not automatically referenced by the compiler, it is necessary to tell it which ones are needed. This switch also allows you to include your own DLLs.
/out: file
eg.
/out:fred.dll
Specifies the filename to which the compiled code is to be written.
/doc: file
eg.
/doc:doc.xml
Requests the production of xml documentation into the specified file (see lesson 19).
/t:type or /target:type
eg.
/t:exe - produce a console executable file (default)
/t:library - produce a dll file
/t:module - creates each file into its own dll, eg. fred.cs will be converted to fred.dll
/t:winexe - produce a windows executable file
This is used to specify the type of output file produced

If you are regularly compiling a program and using a lot of switches in your program, we have found it useful to put the compile command in a batch file rather than writing out the entire command each time.

Preprocessor Directives

Preprocessor directives tags included within class specifications; they are used to give the compiler additional information about regions of code. The following example shows that you can specify areas of code to be compiled or not, depending upon the presence of a tag:

1.

/*

2.

Preprocessor Test

3.

*/

4.

5.

#define MYVAR

6.

public class PreTest

7.

{

8.

    public static void Main()

9.

    {

10.

        #if MYVAR

11.

        print ("Hello");

12.

        #endif

13.

        print ("Andy");

14.

    }

15.

}


In the above, the #define statement on line 5 acts as a boolean: it sets the variable MYVAR to be 'defined' rather than 'undefined'. Because it is defined, the code on line 16 gets compiled. If we were to remove the statement on line 5, the compiler would effectively treat the code on line 11 as commented out.

Note: in the previous version of this page we followed the MSDN documentation in using as our example the variable DEBUG. But it has been pointed out to us by a correspondent that the DEBUG variable is already defined by Visual Studio.NET when a project is compiled as 'debug' rather than 'release'. So if you're building from VS.NET you wouldn't want to explicitly redefine the variable DEBUG like this.

The following gives a list of some of the available preprocessor directives.

DirectiveAction
#define symbolSets symbol to be 'defined' (true)
#undef symbolSets symbol to be 'undefined' (false)
#if symbol [operator symbol2]The if statement evaluates the given expression. The possible operators can be ==, !=, &&, ||. If the expression evaluates to 'true', the code to the #else, #elif or #endif directive is compiled.
#elseUsed in conjunction with the if statement.
#elifUsed in conjunction with the if statement as 'else-if'.
#endifEnds the previous conditional directives
#warning textThe given text appears as a warning in the compiler output
#error textThe given text appears as an error in the compiler output
#line number[file]Outputs a line number, and (optionally) a filename to the compiler output.
#region nameMarks the beginning of a region
#end regionMarks the ends of a region

Attributes

Attributes are used to give extra information to the .NET compiler. C# and the .NET framework have a few built-in attribute types, but it is also possible to create new ones by extending the System.Attribute class. Below we describe a few common uses of attributes.

It is possible to tell the compiler that a class is compliant with the .NET Common Language Specification (discussed in lesson 1) with code like the following:

1.

using System;

2.

3.

[CLSCompliant(true)]

4.

public class myClass

5.

{

6.

// class code

7.

}


Similar code can also be used to indicate that a class has been obsoleted.

Web services (mentioned in lesson 1) also make heavy use of attributes. Demonstrated by the example below, the attribute [ WebMethod ] is used to specify that a particular method is to be exposed as a web service.

1.

[ WebMethod ]

2.

public int Add(int num1, int num2)

3.

{

4.

    return num1+num2;

5.

}


Link Building Information