1.4. C# Program Structure
1.4.1. The .NET templates
The .NET SDK comes with built-in templates for creating projects and files, including console apps,
class libraries, unit test projects, etc. For learning purposes, we will mainly use the console app
template. To see the list of templates, you may issue the dotnet new list
command:
PS C:\Users\tcn85> dotnet new list
These templates matched your input:
Template Name Short Name Language Tags
-------------------------------------------- -------------------------- ---------- --------------------------
ASP.NET Core Web App (Model-View-Controller) mvc [C#],F# Web/MVC
ASP.NET Core Web App (Razor Pages) webapp,razor [C#] Web/MVC/Razor Pages
Blazor Web App blazor [C#] Web/Blazor/WebAssembly
Class Library classlib [C#],F#,VB Common/Library
Console App console [C#],F#,VB Common/Console
We can try out the Console App template, which will give us a “Hello, World” message
when executing. In the terminal, let us
change directory (cd
) into the test directory and issue command dotnet new console
.
The .NET SDK will generate a project for us, which will include the following files and
directories:
The
Program.cs
fileThe
obj
folderThe
testPrj.csproj
fileA
bin
directory will also be created later after the project is built.
PS C:\Users\tcn85> cd test
PS C:\Users\tcn85\test> ls PS C:\Users\tcn85> ls
PS C:\Users\tcn85\test> PS C:\Users\tcn85> ls
PS C:\Users\tcn85\test> dotnet new console
The template "Console App" was created successfully.
Processing post-creation actions...
Restoring C:\Users\tcn85\test\test.csproj:
Determining projects to restore...
Restored C:\Users\tcn85\test\test.csproj (in 175 ms).
Restore succeeded.
PS C:\Users\tcn85\test> ls
Directory: C:\Users\tcn85\test
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 8/7/2024 2:54 PM obj
-a---- 8/7/2024 2:54 PM 105 Program.cs
-a---- 8/7/2024 2:54 PM 252 test.csproj
-a---- 7/26/2024 5:06 PM 0 test.txt
PS C:\Users\tcn85\test>
From the terminal we can open vscode by typing code .
(the dot .
means the current
directory) and Enter.
PS C:\Users\tcn85\test> code .
PS C:\Users\tcn85\test>
VS Code will open. We then choose the Explorer view and click on the Program.cs file. You will see that the Program.cs looks simple as below and we are working the executable code directly.
1// See https://aka.ms/new-console-template for more information
2Console.WriteLine("Hello, World!");
The template is very succinct because of a C# feature called “top-level statements”, with which the compiler automatically performs some tasks such as:
generates a Program class with an entry point method for the application; and
adds a set of implicit
global using
directives such as Microsoft.NET.Sdk to include the most common namespaces.
While this friendly to new users, as we learn more about C# programming,
you will need to learn how to structure your code using namespaces and classes.
To use the old program style, you can use the --use-program-main
option to create a console app project with Main method
. In the example
below, we first create a testPrj folder inside the test2 folder, then change into the
testPrj folder, followed by issuing dotnet new console
with the option --use-program-main
to create a new console project:
tychen@mac:~/test/testPrj$ dotnet new console --use-program-main
This will give us the same project files as running dotnet new console without the “—program-main” option, but the Program.cs file will be different:
tychen@mac:~/test/testPrj$ ls
Program.cs obj testPrj.csproj
1.4.2. The C# Program.cs file
Opening the Program.cs file created by dotnet new console --use-program-main
and you see the template code as:
1namespace testPrj;
2
3class Program
4{
5 static void Main(string[] args)
6 {
7 Console.WriteLine("Hello, World!");
8 }
9}
Some important concepts that you need to learn from this template code example here so we have better ideas about the basic structure of C# programs.
using System;
:Starting .NET 6,
using System
is implicit as defined in the.csproj
file so it is not shown in the Program.cs file. We should know that,System
is a namespace that contains basic defined value and reference types. Theusing
directive, allows you to use the types defined in a namespace without specifying the fully qualified namespace of that type. For example,Console
is a class inside theSystem
namespace and we use the itsWriteLine
method to print to the console. The following example would allow the use of theText
types such as the System.Text.Ascii class and the nested namespace System.Text.Unicode:using System.Text;
namespace
: Thenamespace
keyword is used to declare a scope to organize types (such as classes). For example, we may define a namespace as below to contain unique reference type code elements. If you have some knowledge of object-oriented programming (OOP), you probably have heard of that OOP programs consists of classes. In the example below, you see the types (class, interface, struct, …) are under a namespace and the types are what we use to create functionalities for the application.namespace SampleNamespace { class SampleClass { } interface ISampleInterface { } struct SampleStruct { } enum SampleEnum { a, b } delegate void SampleDelegate(int i); namespace Nested { class SampleClass2 { } } }
An example of namespace is the
System
namespace in .NET. When we runConsole.WriteLine("Hello, World");
, we are actually runningSystem.Console.WriteLine("Hello World!");
We do not specify “System” because it is “imported” already and we can use the types within. The System namespace in .NET contains classes classes that define commonly-used value and reference data types. System engineers use namespace the same way to organize the functionalities in applications. [1]class
: A class is a blueprint for creating objects, which may include the structure, behaviors, and attributes of the objects. A class can be thought of a user-defined data type (reference data type) containingattributes (data), and
methods (actions applied to the data).
In principle, we design one type per file to make code navigation easy.
The
Main
method: The Main method is the entry point of a C# application and therefore the first method invoked when an application is executed. There is only one entry point in a C# program.method
: A method (function) is an object-oriented term for function, which is a series of statements designed to perform certain task. In C#, just like Java, the Main method is the entry point of the program, meaning it is the first method invoked when a program is executed.static
&void
:The modifier
static
means the method can be called without creating a new object from the class.void
means the Main method does not return anything.
string[] args
: Theargs
are called “command line arguments” and in this example the type is string array; meaning when calling this method you send the arguments in and they are zero-indexed as an array.
1.4.3. Solutions and projects
The .NET platform uses solutions and projects to organize code items in specific structure. A solution is a container or workspace for one or more projects, and each project would contain source code files [2]. A web app solution, for example, may include a website project, a database project, and a server-side API project; and each of the project will be named differently under different project folders inside the solution directory.
To create a solution as a workspace, we use the command dotnet new sln
in the solution
(or “workspace”) directory. You then create all your project directories in the solution directory,
and then use the dotnet new console
command inside each of the project directories
to create a console app project in each of the project directories.
If you create a project in a folder using VS Code’s “Create .NET Project” button in the Explorer view,
a solution will be created with the same name as the project. To manage solutions, the Solution Explorer
in VS Code can be used. To create a project without creating a solution, create a directory in command line
and issue the command dotnet new console
to create a new console app project without creating a new solution. [3]
1.4.4. Comments, Curly Braces, and Semicolon
Comments are important as they make code more readable. C# offers single-line and multiple-line comments:
Single-line Comments: Single-line comments start with two forward slashes (//). Any text between // and the end of the line is ignored by C# (will not be executed).
Multi-line Comments: Multi-line comments start with /* and ends with */. Any text between /* and */ will be ignored by C#.
The curly braces { } in C# mark the beginning and the end of a block of code.
Semicolons work as statement terminator character in C# and are required because they prevent syntax ambiguities. Semicolons after method or accessor block, however, is not allowed.
1.4.4.1. Compound Statements (Code Blocks)
A code block (or simply “block”), also referred to as a compound statement, is the grouping of multiple statements into a single statement. While each statement that ends with a semicolon, often it makes sense to see a block of statements as one lexical unit. In C#, a code block is delimited by a pair of curly braces to include a list of statements. For example, the following code shows an if statement, you can see the two highlighted code blocks being compound statements because the statements inside the curly braces. More specifically, line 4-9 is a compound statement of the if statement.
Footnotes