Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Um método é um bloco de código que contém uma série de instruções. Um programa faz com que as instruções sejam executadas chamando o método e especificando os argumentos de método necessários. No C#, todas as instruções executadas são realizadas no contexto de um método.
O Main
método é o ponto de entrada para cada aplicativo C# e é chamado pelo CLR (Common Language Runtime) quando o programa é iniciado. Em um aplicativo que usa instruções de nível superior, o Main
método é gerado pelo compilador e contém todas as instruções de nível superior.
Observação
Este artigo discute métodos nomeados. Para obter informações sobre funções anônimas, consulte expressões lambda.
Assinaturas de método
Os métodos são declarados em uma classe, struct ou interface especificando o nível de acesso, como public
ou private
, modificadores opcionais, como abstract
ou sealed
, o valor retornado, o nome do método e quaisquer parâmetros de método. Essas partes juntas são a assinatura do método.
Importante
Um tipo de retorno de um método não faz parte da assinatura do método para fins de sobrecarga de método. No entanto, ele faz parte da assinatura do método ao determinar a compatibilidade entre um delegado e o método para o qual ele aponta.
Os parâmetros de método estão entre parênteses e separados por vírgulas. Parênteses vazios indicam que o método não requer parâmetros. Esta classe contém quatro métodos:
abstract class Motorcycle
{
// Anyone can call this.
public void StartEngine() {/* Method statements here */ }
// Only derived classes can call this.
protected void AddGas(int gallons) { /* Method statements here */ }
// Derived classes can override the base class implementation.
public virtual int Drive(int miles, int speed) { /* Method statements here */ return 1; }
// Derived classes must implement this.
public abstract double GetTopSpeed();
}
Acesso a método
Chamar um método em um objeto é como acessar um campo. Após o nome do objeto, adicione um período, o nome do método e parênteses. Os argumentos são listados dentro dos parênteses e separados por vírgulas. Os métodos da Motorcycle
classe podem, portanto, ser chamados como no exemplo a seguir:
class TestMotorcycle : Motorcycle
{
public override double GetTopSpeed()
{
return 108.4;
}
static void Main()
{
TestMotorcycle moto = new TestMotorcycle();
moto.StartEngine();
moto.AddGas(15);
moto.Drive(5, 20);
double speed = moto.GetTopSpeed();
Console.WriteLine($"My top speed is {speed}");
}
}
Parâmetros de método versus argumentos
A definição do método especifica os nomes e tipos de quaisquer parâmetros obrigatórios. Quando o código de chamada invoca o método, ele fornece valores concretos chamados argumentos para cada parâmetro. Os argumentos devem ser compatíveis com o tipo de parâmetro, mas o nome do argumento (se houver) usado no código de chamada não precisa ser o mesmo que o parâmetro nomeado definido no método. Por exemplo:
public void Caller()
{
int numA = 4;
// Call with an int variable.
int productA = Square(numA);
int numB = 32;
// Call with another int variable.
int productB = Square(numB);
// Call with an integer literal.
int productC = Square(12);
// Call with an expression that evaluates to int.
productC = Square(productA * 3);
}
int Square(int i)
{
// Store input argument in a local variable.
int input = i;
return input * input;
}
Passando por referência versus passando por valor
Por padrão, quando uma instância de um tipo de valor é passada para um método, sua cópia é passada em vez da própria instância. Portanto, as alterações no argumento não têm efeito sobre a instância original no método de chamada. Para passar uma instância de tipo de valor por referência, use a palavra-chave ref
. Para obter mais informações, consulte Como passar parâmetros de Value-Type.
Quando um objeto de um tipo de referência é passado para um método, uma referência ao objeto é passada. Ou seja, o método não recebe o objeto em si, mas um argumento que indica o local do objeto. Se você alterar um membro do objeto usando essa referência, a alteração será refletida no argumento no método de chamada, ainda que você passe o objeto por valor.
Você cria um tipo de referência usando a class
palavra-chave, como mostra o exemplo a seguir:
public class SampleRefType
{
public int value;
}
Agora, se você passar um objeto baseado nesse tipo para um método, uma referência ao objeto será passada. O exemplo a seguir passa um objeto de tipo SampleRefType
para o método ModifyObject
:
public static void TestRefType()
{
SampleRefType rt = new SampleRefType();
rt.value = 44;
ModifyObject(rt);
Console.WriteLine(rt.value);
}
static void ModifyObject(SampleRefType obj)
{
obj.value = 33;
}
O exemplo faz essencialmente a mesma coisa que o exemplo anterior em que passa um argumento por valor para um método. Mas, como um tipo de referência é usado, o resultado é diferente. A modificação feita no campo ModifyObject
do parâmetro, value
, também altera o campo obj
do argumento, value
, no método rt
. O TestRefType
método exibe 33 como saída.
Para obter mais informações sobre como passar tipos de referência por referência e por valor, consulte Passando parâmetros de tipo de referência e Tipos de referência.
Valores retornados
Os métodos podem retornar um valor para o chamador. Se o tipo de retorno (o tipo listado antes do nome do método) não for void
, o método poderá retornar o valor usando a instrução return
. Uma instrução com a return
palavra-chave seguida por um valor que corresponde ao tipo de retorno retornará esse valor para o chamador do método.
O valor pode ser retornado ao chamador por valor ou por referência. Valores são retornados ao chamador por referência se a ref
palavra-chave é usada na assinatura do método e segue cada palavra-chave return
. Por exemplo, a assinatura do método a seguir e a instrução return indicam que o método retorna uma variável nomeada estDistance
por referência ao chamador.
public ref double GetEstimatedDistance()
{
return ref estDistance;
}
A palavra-chave return
também interrompe a execução do método. Se o tipo de retorno for void
, uma instrução return
sem um valor ainda será útil para interromper a execução do método. Sem a return
palavra-chave, o método interromperá a execução quando chegar ao final do bloco de código. Métodos com um tipo de retorno não nulo são necessários para usar a return
palavra-chave para retornar um valor. Por exemplo, esses dois métodos usam a palavra-chave return
para retornar inteiros:
class SimpleMath
{
public int AddTwoNumbers(int number1, int number2)
{
return number1 + number2;
}
public int SquareANumber(int number)
{
return number * number;
}
}
Para usar um valor retornado de um método, o método de chamada pode usar o método chamado em qualquer lugar em que um valor do mesmo tipo seria suficiente. Você também pode atribuir o valor retornado a uma variável. Por exemplo, os dois exemplos de código a seguir atingem a mesma meta:
int result = obj.AddTwoNumbers(1, 2);
result = obj.SquareANumber(result);
// The result is 9.
Console.WriteLine(result);
result = obj.SquareANumber(obj.AddTwoNumbers(1, 2));
// The result is 9.
Console.WriteLine(result);
O uso de uma variável local, nesse caso, result
para armazenar um valor é opcional. Ele pode ajudar na legibilidade do código ou pode ser necessário se você precisar armazenar o valor original do argumento para todo o escopo do método.
Para usar um valor retornado por referência de um método, você deve declarar uma variável local ref se pretende modificar seu valor. Por exemplo, se o Planet.GetEstimatedDistance
método retornar um Double valor por referência, você poderá defini-lo como uma variável local ref com código como o seguinte:
ref double distance = ref Planet.GetEstimatedDistance();
Retornar uma matriz multidimensional de um método, M
que modifica o conteúdo da matriz não é necessário se a função de chamada passou a matriz para M
. Você pode retornar a matriz resultante de M
para melhorar o estilo ou o fluxo funcional dos valores, mas isso não é necessário porque o C# passa todos os tipos de referência por valor, e o valor de uma referência de matriz é o ponteiro para a matriz. No método M
, todas as alterações no conteúdo da matriz são observáveis por qualquer código que tenha uma referência à matriz, conforme mostrado no exemplo a seguir:
static void Main(string[] args)
{
int[,] matrix = new int[2, 2];
FillMatrix(matrix);
// matrix is now full of -1
}
public static void FillMatrix(int[,] matrix)
{
for (int i = 0; i < matrix.GetLength(0); i++)
{
for (int j = 0; j < matrix.GetLength(1); j++)
{
matrix[i, j] = -1;
}
}
}
Métodos assíncronos
Usando o recurso async, você pode invocar métodos assíncronos sem usar retornos de chamada explícitos ou dividir manualmente seu código entre vários métodos ou expressões lambda.
Se você marcar um método com o modificador assíncrono , poderá usar o operador await no método. Quando o controle atinge uma expressão await no método assíncrono, ele retorna para o chamador e o progresso no método é suspenso até a tarefa aguardada ser concluída. Quando a tarefa for concluída, a execução poderá ser retomada no método.
Observação
Um método assíncrono retorna para o chamador quando encontra o primeiro objeto esperado que ainda não está completo ou chega ao final do método assíncrono, o que ocorrer primeiro.
Um método assíncrono normalmente tem um tipo de retorno de Task<TResult>, TaskIAsyncEnumerable<T>ou void
. O tipo de retorno void
é usado principalmente para definir manipuladores de eventos, nos quais o tipo de retorno void
é necessário. Um método assíncrono que retorna void
não pode ser aguardado e o chamador de um método de retorno nulo não pode capturar as exceções que esse método gera. Um método assíncrono pode ter qualquer tipo de retorno semelhante a uma tarefa.
No exemplo a seguir, DelayAsync
é um método assíncrono que tem um tipo de retorno de Task<TResult>.
DelayAsync
tem uma instrução return
que retorna um número inteiro. Portanto, a declaração do método DelayAsync
deve ter um tipo de retorno Task<int>
. Como o tipo de retorno é Task<int>
, a avaliação da await
expressão em DoSomethingAsync
produz um inteiro, como demonstra a instrução a seguir: int result = await delayTask
.
O Main
método é um exemplo de um método assíncrono que tem um tipo de retorno de Task. Ele vai para o método DoSomethingAsync
e, como ele é expresso com uma única linha, pode omitir as palavras-chave async
e await
. Como DoSomethingAsync
é um método assíncrono, a tarefa para a chamada DoSomethingAsync
deve ser aguardada, como mostra a seguinte instrução: await DoSomethingAsync();
.
class Program
{
static Task Main() => DoSomethingAsync();
static async Task DoSomethingAsync()
{
Task<int> delayTask = DelayAsync();
int result = await delayTask;
// The previous two statements may be combined into
// the following statement.
//int result = await DelayAsync();
Console.WriteLine($"Result: {result}");
}
static async Task<int> DelayAsync()
{
await Task.Delay(100);
return 5;
}
}
// Example output:
// Result: 5
Um método assíncrono não pode declarar parâmetros ref ou out , mas pode chamar métodos que têm esses parâmetros.
Para obter mais informações sobre métodos assíncronos, consulte Programação assíncrona com async e await e Tipos de retorno assíncronos.
Definições do corpo da expressão
É comum ter definições de método que simplesmente retornam imediatamente com o resultado de uma expressão ou que tenham uma única instrução como o corpo do método. Há um atalho de sintaxe para definir esses métodos usando =>
:
public Point Move(int dx, int dy) => new Point(x + dx, y + dy);
public void Print() => Console.WriteLine(First + " " + Last);
// Works with operators, properties, and indexers too.
public static Complex operator +(Complex a, Complex b) => a.Add(b);
public string Name => First + " " + Last;
public Customer this[long id] => store.LookupCustomer(id);
Se o método retornar void
ou for um método assíncrono, o corpo do método deverá ser uma expressão de instrução (igual a lambdas). Para propriedades e indexadores, eles devem ser somente leitura e você não usa a palavra-chave do acessador get
.
Iteradores
Um iterador realiza uma iteração personalizada em uma coleção, como uma lista ou uma matriz. Um iterador usa a instrução de retorno de rendimento para retornar cada elemento um de cada vez. Quando uma instrução yield return
for atingida, o local atual no código será lembrado. A execução é reiniciada desse local quando o iterador é chamado na próxima vez.
Você chama um iterador do código do cliente usando uma instrução foreach.
O tipo de retorno de um iterador pode ser IEnumerable, IEnumerable<T>, IAsyncEnumerable<T>, IEnumerator ou IEnumerator<T>.
Para obter mais informações, consulte Iteradores.
Especificação da linguagem C#
Para obter mais informações, consulte a Especificação da Linguagem C# . A especificação de idioma é a fonte definitiva para a sintaxe e o uso de C#.