Skip to content

Contact sales

By filling out this form and clicking submit, you acknowledge our privacy policy.

Method Entry and Exit Points in C#

Apr 3, 2020 • 5 Minute Read

Introduction

Every C# application has an entry point called the main method. This method is invoked first, and whatever business logic is implemented in your app is controlled from there. In this guide, we'll discover how the CLR knows which method to call and when to call it. We'll also see the difference in this context between executable applications and libraries.

CLR

CLR is short for common language runtime. Its sole purpose is to translate your code so that the hardware of your machine can understand your intentions. When you write a code in C#, it is referred to as source code. The language specific compiler turns that code into something called MSIL, or Microsoft Intermediate Language. Sometimes it is also referred to as CIL, short for Common Intermediate Language, or just simply IL, or Intermediate Language. This intermediate state of your code also holds language-specific metadata about language-specific type implementation and the actual implementation of each of your classes, functions, and so on. The CLR steps in to provide a service and a runtime for your code to live in. The JIT, or just-in-time compiler, also lives in this realm and turns your code into machine code, which is in turn executed by the CPU.

Entry Points

The most basic example of an entry point is the following:

      using System;

namespace Pluralsight
{
      public class EntryPoints 
    {              
        public static void Main()
        {
            Console.WriteLine("I am the beginning.");
        }
    }
}
    

When you have an app compiled to an exe file, you have two distinct approaches for entry points. One is synchronous and the other is asynchronous. The type of the Main() function is always static. You have the option to choose if you are to return a status code after the application exits or not. If you want to do this, use int, otherwise use void. When the int type is specified, the value is passed back to the execution environment, as in C or C++.

Synchronous Main() methods:

  1. static void Main()
  2. static void Main(string[] args)
  3. static int Main()
  4. static int Main(string[] args)

Asynchronous Main() methods:

  1. static Task Main()
  2. static Task<int> Main()
  3. static Task Main(string[])
  4. static Task<int> Main(string[])

The Main() method can only have string[] types of arguments, and it can return either void, int, or when used in async context, either Task or Task<T>.

In special corner cases you can define multiple Main() methods as entry points, but during compilation you need to specify which one is the entry point; otherwise the compilation will fail.

Libraries

Libraries are used to package functionality and allow distribution, which lets other developers speed up development by reusing code. Due to this, an entry point cannot be specified for libraries because the entry point's sole purpose is to kick off the execution. So in terms of development, you should consider your code a library if you do not specify an entry point method as a Main() function.

An example library:

      using System;

namespace Pluralsight
{
    public class Server
    {
        public string Name;
        public Server(string name) {
            Name = name;
        }
    }
}
    

Exit Points

Exit points serve as a control mechanism. They transfer back control to the caller with either a return value of a specific type or void. In the Main() method, reaching the exit point means our application is closed. But you can define other functions, as in the example below.

      using System;

namespace Pluralsight
{
    public class Server
    {
        public string Name;
        public int RestartServer() {
            try {
                Console.WriteLine("Restarting server...");
                // ...

                Console.WriteLine("Successfully restarted");
                return 1;
            }
            catch {
                Console.WriteLine("Failed to restar the server...");
                return 0;
            }
            
        }
        public Server(string name)
        {
            Name = name;
        }
    }
}
    

In this class, we have a RestartServer() method. When this method is called, it will try to restart the server. If it is successful, the 1 value is passed back to the caller, and otherwise the 0 value is passed back. This function has two exit points, and they allow the caller to make a decision about whether the restart was successful or not based on the value, regardless of the text printed to the console.

Conclusion

In this guide, you were introduced to the concept of entry points and exit points. You saw how CLR executes your code and what it looks for when you have an executable application. I hope this guide has been informative to you and I would like to thank you for reading it.