Instruções de nível superior – Programas sem métodos Main

Não é preciso incluir explicitamente um método Main em um projeto de aplicativo de console. Em vez disso, você pode usar o recurso de instruções de nível superior para minimizar o volume de código que precisa escrever.

Instruções de alto nível permitem que você escreva código executável diretamente na raiz de um arquivo, eliminando a necessidade de encapsular seu código em uma classe ou método. Isso significa que você pode criar programas sem a cerimônia de uma classe Program e um método Main. Nesse caso, o compilador gera uma classe Program com um método de ponto de entrada para o aplicativo. O nome do método gerado não é Main, é um detalhe de implementação que seu código não pode referenciar diretamente.

Aqui está um arquivo Program.cs que corresponde a um programa C# completo no C# 10:

Console.WriteLine("Hello World!");

Instruções de nível superior permitem que você escreva programas simples para utilitários pequenos, como o Azure Functions e o GitHub Actions. Elas também simplificam para novos programadores C# começar a aprender e escrever código.

As seções a seguir explicam as regras sobre o que você pode ou não fazer com instruções de nível superior.

Apenas um arquivo de nível superior

Cada aplicativo deve ter apenas um ponto de entrada. Cada projeto pode ter apenas um arquivo com instruções de nível superior. Colocar instruções de nível superior em mais de um arquivo de um projeto resulta no seguinte erro do compilador:

CS8802 Somente uma unidade de compilação pode conter instruções de nível superior.

Os projetos podem ter um número indefinido de arquivos de código-fonte adicionais que não têm instruções de nível superior.

Nenhum outro ponto de entrada

Você pode escrever um método Main explicitamente, mas ele não pode funcionar como um ponto de entrada. O compilador emite o seguinte aviso:

CS7022 O ponto de entrada do programa é o código global, ignorando o ponto de entrada "Main()".

Em um projeto com instruções de nível superior, você não pode usar a opção do compilador -main para selecionar o ponto de entrada, mesmo que o projeto tenha um ou mais métodos Main.

using diretivas

Se você incluir o uso de diretivas, elas deverão vir primeiro no arquivo, como neste exemplo:

using System.Text;

StringBuilder builder = new();
builder.AppendLine("The following arguments are passed:");

// Display the command line arguments using the args variable.
foreach (var arg in args)
{
    builder.AppendLine($"Argument={arg}");
}

Console.WriteLine(builder.ToString());

// Return a success code.
return 0;

Namespace global

As instruções de nível superior estão implicitamente no namespace global.

Namespaces e definições de tipo

Um arquivo com instruções de nível superior também pode conter namespaces e definições de tipo, mas devem vir após as instruções de nível superior. Por exemplo:

MyClass.TestMethod();
MyNamespace.MyClass.MyMethod();

public class MyClass
{
    public static void TestMethod()
    {
        Console.WriteLine("Hello World!");
    }
}

namespace MyNamespace
{
    class MyClass
    {
        public static void MyMethod()
        {
            Console.WriteLine("Hello World from MyNamespace.MyClass.MyMethod!");
        }
    }
}

args

Instruções de nível superior podem fazer referência à variável args para acessar quaisquer argumentos de linha de comando que foram inseridos. A variável args nunca será nula, mas o Length dela será zero se nenhum argumento de linha de comando tiver sido fornecido. Por exemplo:

if (args.Length > 0)
{
    foreach (var arg in args)
    {
        Console.WriteLine($"Argument={arg}");
    }
}
else
{
    Console.WriteLine("No arguments");
}

await

Você pode chamar um método assíncrono usando await. Por exemplo:

Console.Write("Hello ");
await Task.Delay(5000);
Console.WriteLine("World!");

Código de saída do processo

Para retornar um valor int quando o aplicativo terminar, use a instrução return como faria em um método Main que retorna um int. Por exemplo:

string? s = Console.ReadLine();

int returnValue = int.Parse(s ?? "-1");
return returnValue;

Método de ponto de entrada implícito

O compilador gera um método para servir como o ponto de entrada do programa para um projeto com instruções de nível superior. A assinatura do método depende se as instruções de nível superior contêm a palavra-chave await ou a instrução return. A tabela a seguir mostra como seria a assinatura do método, usando o nome de método Main na tabela para fins de conveniência.

O código de nível superior contém Assinatura Main implícita
await e return static async Task<int> Main(string[] args)
await static async Task Main(string[] args)
return static int Main(string[] args)
Não await nem return static void Main(string[] args)

Especificação da linguagem C#

Para obter mais informações, consulte a Especificação da linguagem C#. A especificação da linguagem é a fonte definitiva para a sintaxe e o uso de C#.

Especificação de recurso – Instruções de nível superior