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

A partir do C# 9, você não precisa incluir explicitamente um Main método 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 código que você precisa escrever. Nesse caso, o compilador gera um ponto de entrada de classe Main e método para o aplicativo.

Aqui está um arquivo Program.cs que é 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 Azure Functions e GitHub Actions. Eles também simplificam o aprendizado e a escrita de código para novos programadores em C#.

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

Um aplicativo deve ter apenas um ponto de entrada. Um 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 em um projeto resulta no seguinte erro do compilador:

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

Um projeto pode ter qualquer número 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 Main método 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 Main métodos.

using Directivas

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


using System.Text;

StringBuilder builder = new();
builder.AppendLine("Hello");
builder.AppendLine("World!");

Console.WriteLine(builder.ToString());

Namespace global

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 eles 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 referenciar args a variável para acessar os argumentos de linha de comando que foram inseridos. A args variável nunca será nula, mas Length 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 para o processo

Para retornar um int valor quando o aplicativo terminar, use a instrução como faria em um método que retorna um return Main 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. O nome desse método não é, na verdade, , é um detalhe de implementação Main que seu código não pode referenciar diretamente. A assinatura do método depende se as instruções de nível superior contêm a await palavra-chave ou a return instrução . A tabela a seguir mostra a aparência da assinatura do método, usando o nome do Main método na tabela para sua 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 ou 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