MétodosMethods

Um método é um bloco de código que contém uma série de instruções.A method is a code block that contains a series of statements. Um programa faz com que as instruções sejam executadas chamando o método e especificando os argumentos de método necessários.A program causes the statements to be executed by calling the method and specifying any required method arguments. No C#, todas as instruções executadas são realizadas no contexto de um método.In C#, every executed instruction is performed in the context of a method. O método Main é o ponto de entrada para todos os aplicativos C# e é chamado pelo CLR (Common Language Runtime) quando o programa é iniciado.The Main method is the entry point for every C# application and it is called by the common language runtime (CLR) when the program is started.

Observação

Este tópico aborda os métodos nomeados.This topic discusses named methods. Para obter informações sobre funções anônimas, consulte Funções anônimas.For information about anonymous functions, see Anonymous Functions.

Esse tópico contém as seguintes seções:This topic contains the following sections:

Assinaturas de métodoMethod signatures

Os métodos são declarados em uma class ou struct especificando:Methods are declared in a class or struct by specifying:

  • Um nível de acesso opcional, como public ou private.An optional access level, such as public or private. O padrão é private.The default is private.
  • Modificadores opcionais como abstract ou sealed.Optional modifiers such as abstract or sealed.
  • O valor retornado ou void se o método não tiver nenhum.The return value, or void if the method has none.
  • O nome do método.The method name.
  • Quaisquer parâmetros de método.Any method parameters. Os parâmetros de método estão entre parênteses e separados por vírgulas.Method parameters are enclosed in parentheses and are separated by commas. Parênteses vazios indicam que o método não requer parâmetros.Empty parentheses indicate that the method requires no parameters.

Essas partes juntas formam a assinatura do método.These parts together form the method signature.

Observação

Um tipo de retorno de um método não faz parte da assinatura do método para fins de sobrecarga de método.A return type of a method is not part of the signature of the method for the purposes of method overloading. 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.However, it is part of the signature of the method when determining the compatibility between a delegate and the method that it points to.

O exemplo a seguir define uma classe chamada Motorcycle que contém cinco métodos:The following example defines a class named Motorcycle that contains five methods:

using System;

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 can override the base class implementation.
   public virtual int Drive(TimeSpan time, int speed) { /* Method statements here */ return 0; }

   // Derived classes must implement this.
   public abstract double GetTopSpeed(); 
}

Observe que a classe Motorcycle inclui um método sobrecarregado, Drive.Note that the Motorcycle class includes an overloaded method, Drive. Dois métodos têm o mesmo nome, mas devem ser diferenciados por seus tipos de parâmetro.Two methods have the same name, but must be differentiated by their parameter types.

Invocação de métodoMethod invocation

Os métodos podem ser de instância ou estáticos.Methods can be either instance or static. Invocar um método de instância requer que você crie uma instância de um objeto e chame o método nesse objeto. Um método de instância opera nessa instância e seus dados.Invoking an instance method requires that you instantiate an object and call the method on that object; an instance method operates on that instance and its data. Você invoca um método estático referenciando o nome do tipo ao qual o método pertence; os métodos estáticos não operam nos dados da instância.You invoke a static method by referencing the name of the type to which the method belongs; static methods do not operate on instance data. Tentar chamar um método estático por meio de uma instância do objeto gera um erro do compilador.Attempting to call a static method through an object instance generates a compiler error.

Chamar um método é como acessar um campo.Calling a method is like accessing a field. Após o nome do objeto (se você estiver chamando um método de instância) ou o nome do tipo (se você estiver chamando um método static), adicione um ponto, o nome do método e parênteses.After the object name (if you are calling an instance method) or the type name (if you are calling a static method), add a period, the name of the method, and parentheses. Os argumentos são listados dentro dos parênteses e são separados por vírgulas.Arguments are listed within the parentheses, and are separated by commas.

A definição do método especifica os nomes e tipos de quaisquer parâmetros obrigatórios.The method definition specifies the names and types of any parameters that are required. Quando um chamador invoca o método, ele fornece valores concretos, chamados argumentos, para cada parâmetro.When a caller invokes the method, it provides concrete values, called arguments, for each parameter. Os argumentos devem ser compatíveis com o tipo de parâmetro, mas o nome do argumento, se for usado no código de chamada, não precisa ser o mesmo que o parâmetro denominado definido no método.The arguments must be compatible with the parameter type, but the argument name, if one is used in the calling code, does not have to be the same as the parameter named defined in the method. No exemplo a seguir, o método Square inclui um único parâmetro do tipo int chamado i.In the following example, the Square method includes a single parameter of type int named i. A primeira chamada do método passa para o método Square uma variável do tipo int chamada num, a segunda, uma constante numérica e a terceira, uma expressão.The first method call passes the Square method a variable of type int named num; the second, a numeric constant; and the third, an expression.

public class Example
{
   public static void Main()
   {
      // Call with an int variable.
      int num = 4;
      int productA = Square(num);

      // Call with an integer literal.
      int productB = Square(12);

      // Call with an expression that evaluates to int.
      int productC = Square(productA * 3);
   }
   
   static int Square(int i)
   {
      // Store input argument in a local variable.
      int input = i;
      return input * input;
   }
}

A forma mais comum de invocação de método usa argumentos posicionais, ela fornece os argumentos na mesma ordem que os parâmetros de método.The most common form of method invocation used positional arguments; it supplies arguments in the same order as method parameters. Os métodos da classe Motorcycle, podem, portanto, ser chamados como no exemplo a seguir.The methods of the Motorcycle class can therefore be called as in the following example. A chamada para o método Drive, por exemplo, inclui dois argumentos que correspondem aos dois parâmetros na sintaxe do método.The call to the Drive method, for example, includes two arguments that correspond to the two parameters in the method's syntax. O primeiro se torna o valor do parâmetro miles, o segundo o valor do parâmetro speed.The first becomes the value of the miles parameter, the second the value of the speed parameter.

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 {0}", speed);            
   }
}

Você também pode usar argumentos nomeados em vez de argumentos posicionais ao invocar um método.You can also used named arguments instead of positional arguments when invoking a method. Ao usar argumentos nomeados, você especifica o nome do parâmetro seguido por dois pontos (":") e o argumento.When using named arguments, you specify the parameter name followed by a colon (":") and the argument. Os argumentos do método podem aparecer em qualquer ordem, desde que todos os argumentos necessários estejam presentes.Arguments to the method can appear in any order, as long as all required arguments are present. O exemplo a seguir usa argumentos nomeados para invocar o método TestMotorcycle.Drive.The following example uses named arguments to invoke the TestMotorcycle.Drive method. Neste exemplo, os argumentos nomeados são passados na ordem oposta da lista de parâmetros do método.In this example, the named arguments are passed in the opposite order from the method's parameter list.

using System;

class TestMotorcycle : Motorcycle
{
   public override int Drive(int miles, int speed)
   {
      return (int) Math.Round( ((double)miles) / speed, 0);
   }

   public override double GetTopSpeed()
   {
      return 108.4;
   }

   static void Main()
   {
      
      TestMotorcycle moto = new TestMotorcycle();
      moto.StartEngine();
      moto.AddGas(15);
      var travelTime = moto.Drive(speed: 60, miles: 170);
      Console.WriteLine("Travel time: approx. {0} hours", travelTime);            
   }
}
// The example displays the following output:
//      Travel time: approx. 3 hours

Você pode invocar um método usando argumentos posicionais e argumentos nomeados.You can invoke a method using both positional arguments and named arguments. No entanto, um argumento posicional não pode seguir um argumento nomeado.However, a positional argument cannot follow a named argument. O exemplo a seguir invoca o método TestMotorcycle.Drive do exemplo anterior usando um argumento posicional e um argumento nomeado.The following example invokes the TestMotorcycle.Drive method from the previous example using one positional argument and one named argument.

var travelTime = moto.Drive(170, speed: 55);

Métodos herdados e substituídosInherited and overridden methods

Além dos membros que são definidos explicitamente em um tipo, um tipo herda membros definidos em suas classes base.In addition to the members that are explicitly defined in a type, a type inherits members defined in its base classes. Como todos os tipos no sistema de tipos gerenciado são herdados direta ou indiretamente da classe Object, todos os tipos herdam seus membros, como Equals(Object), GetType() e ToString().Since all types in the managed type system inherit directly or indirectly from the Object class, all types inherit its members, such as Equals(Object), GetType(), and ToString(). O exemplo a seguir define uma classe Person, instancia dois objetos Person e chama o método Person.Equals para determinar se os dois objetos são iguais.The following example defines a Person class, instantiates two Person objects, and calls the Person.Equals method to determine whether the two objects are equal. O método Equals, no entanto, não é definido na classe Person, ele é herdado do Object.The Equals method, however, is not defined in the Person class; it is inherited from Object.

using System;

public class Person
{
   public String FirstName;
}

public class Example
{
   public static void Main()
   {
      var p1 = new Person();
      p1.FirstName = "John";
      var p2 = new Person();
      p2.FirstName = "John";
      Console.WriteLine("p1 = p2: {0}", p1.Equals(p2));
   }
}
// The example displays the following output:
//      p1 = p2: False

Tipos podem substituir membros herdados usando a palavra-chave override e fornecendo uma implementação para o método substituído.Types can override inherited members by using the override keyword and providing an implementation for the overridden method. A assinatura do método precisa ser igual à do método substituído.The method signature must be the same as that of the overridden method. O exemplo a seguir é semelhante ao anterior, exceto que ele substitui o método Equals(Object).The following example is like the previous one, except that it overrides the Equals(Object) method. (Ele também substitui o método GetHashCode(), uma vez que os dois métodos destinam-se a fornecer resultados consistentes.)(It also overrides the GetHashCode() method, since the two methods are intended to provide consistent results.)

using System;

public class Person
{
   public String FirstName;

   public override bool Equals(object obj)
   {
      var p2 = obj as Person; 
      if (p2 == null)
         return false;
      else
         return FirstName.Equals(p2.FirstName);
   }

   public override int GetHashCode()
   {
      return FirstName.GetHashCode();
   } 
}

public class Example
{
   public static void Main()
   {
      var p1 = new Person();
      p1.FirstName = "John";
      var p2 = new Person();
      p2.FirstName = "John";
      Console.WriteLine("p1 = p2: {0}", p1.Equals(p2));
   }
}
// The example displays the following output:
//      p1 = p2: True

Passando parâmetrosPassing parameters

Os tipos no C# são tipos de valor ou tipos de referência.Types in C# are either value types or reference types. Para obter uma lista de tipos de valor internos, consulte Tipos e variáveis.For a list of built-in value types, see Types and variables. Por padrão, os tipos de referência e tipos de valor são passados para um método por valor.By default, both value types and reference types are passed to a method by value.

Passando parâmetros por valorPassing parameters by value

Quando um tipo de valor é passado para um método por valor, uma cópia do objeto, em vez do próprio objeto, é passada para o método.When a value type is passed to a method by value, a copy of the object instead of the object itself is passed to the method. Portanto, as alterações no objeto do método chamado não têm efeito no objeto original quando o controle retorna ao chamador.Therefore, changes to the object in the called method have no effect on the original object when control returns to the caller.

O exemplo a seguir passa um tipo de valor para um método por valor e o método chamado tenta alterar o valor do tipo de valor.The following example passes a value type to a method by value, and the called method attempts to change the value type's value. Ele define uma variável do tipo int, que é um tipo de valor, inicializa o valor para 20 e o passa para um método chamado ModifyValue que altera o valor da variável para 30.It defines a variable of type int, which is a value type, initializes its value to 20, and passes it to a method named ModifyValue that changes the variable's value to 30. No entanto, quando o método retorna, o valor da variável permanece inalterado.When the method returns, however, the variable's value remains unchanged.

using System;

public class Example
{
   public static void Main()
   {
      int value = 20;
      Console.WriteLine("In Main, value = {0}", value);
      ModifyValue(value);
      Console.WriteLine("Back in Main, value = {0}", value);
   }

   static void ModifyValue(int i)
   {
      i = 30;
      Console.WriteLine("In ModifyValue, parameter value = {0}", i);
      return;
   }
}
// The example displays the following output:
//      In Main, value = 20
//      In ModifyValue, parameter value = 30
//      Back in Main, value = 20

Quando um objeto do tipo de referência é passado para um método por valor, uma referência ao objeto é passada por valor.When an object of a reference type is passed to a method by value, a reference to the object is passed by value. Ou seja, o método recebe não o objeto em si, mas um argumento que indica o local do objeto.That is, the method receives not the object itself, but an argument that indicates the location of the object. Se você alterar um membro do objeto usando essa referência, a alteração será refletida no objeto quando o controle retornar para o método de chamada.If you change a member of the object by using this reference, the change is reflected in the object when control returns to the calling method. No entanto, substituir o objeto passado para o método não tem efeito no objeto original quando o controle retorna para o chamador.However, replacing the object passed to the method has no effect on the original object when control returns to the caller.

O exemplo a seguir define uma classe (que é um tipo de referência) chamada SampleRefType.The following example defines a class (which is a reference type) named SampleRefType. Ele cria uma instância de um objeto SampleRefType, atribui 44 ao seu campo value e passa o objeto para o método ModifyObject.It instantiates a SampleRefType object, assigns 44 to its value field, and passes the object to the ModifyObject method. Este exemplo faz essencialmente a mesma coisa que o exemplo anterior, ele passa um argumento por valor para um método.This example does essentially the same thing as the previous example -- it passes an argument by value to a method. Mas como um tipo de referência é usado, o resultado é diferente.But because a reference type is used, the result is different. A modificação feita em ModifyObject para o campo obj.value também muda o campo value do argumento, rt, no método Main para 33, como a saída do exemplo mostra.The modification that is made in ModifyObject to the obj.value field also changes the value field of the argument, rt, in the Main method to 33, as the output from the example shows.

using System;

public class SampleRefType
{
    public int value;
}

public class Example
{
    public static void Main()
    {
        var rt = new SampleRefType();
        rt.value = 44;
        ModifyObject(rt);
        Console.WriteLine(rt.value);
    }
        
    static void ModifyObject(SampleRefType obj)
    {
        obj.value = 33;
    }
}

Passando parâmetros por referênciaPassing parameters by reference

Você passa um parâmetro por referência quando deseja alterar o valor de um argumento em um método e deseja refletir essa alteração quando o controle retorna para o método de chamada.You pass a parameter by reference when you want to change the value of an argument in a method and want to reflect that change when control returns to the calling method. Para passar um parâmetro por referência, use a palavra-chave ref ou out.To pass a parameter by reference, you use the ref or out keyword. Você também pode passar um valor por referência para evitar a cópia e ainda evitar modificações usando a palavra-chave in.You can also pass a value by reference to avoid copying but still prevent modifications using the in keyword.

O exemplo a seguir é idêntico ao anterior, exceto que o valor é passado por referência para o método ModifyValue.The following example is identical to the previous one, except the value is passed by reference to the ModifyValue method. Quando o valor do parâmetro é modificado no método ModifyValue, a alteração no valor é refletida quando o controle retorna ao chamador.When the value of the parameter is modified in the ModifyValue method, the change in value is reflected when control returns to the caller.

using System;

public class Example
{
   public static void Main()
   {
      int value = 20;
      Console.WriteLine("In Main, value = {0}", value);
      ModifyValue(ref value);
      Console.WriteLine("Back in Main, value = {0}", value);
   }

   static void ModifyValue(ref int i)
   {
      i = 30;
      Console.WriteLine("In ModifyValue, parameter value = {0}", i);
      return;
   }
}
// The example displays the following output:
//      In Main, value = 20
//      In ModifyValue, parameter value = 30
//      Back in Main, value = 30

Um padrão comum que usa parâmetros pela referência envolve a troca os valores das variáveis.A common pattern that uses by ref parameters involves swapping the values of variables. Você passa duas variáveis para um método por referência e o método troca seus conteúdos.You pass two variables to a method by reference, and the method swaps their contents. O exemplo a seguir troca valores inteiros.The following example swaps integer values.

using System;

public class Example
{
   static void Main()
   {
      int i = 2, j = 3;
      System.Console.WriteLine("i = {0}  j = {1}" , i, j);

      Swap(ref i, ref j);

      System.Console.WriteLine("i = {0}  j = {1}" , i, j);
   }

   static void Swap(ref int x, ref int y)
   {
      int temp = x;
      x = y;
      y = temp;
   }   
}
// The example displays the following output:
//      i = 2  j = 3
//      i = 3  j = 2

Passar um parâmetro de tipo de referência permite que você altere o valor da própria referência, em vez de o valor de seus campos ou elementos individuais.Passing a reference-type parameter allows you to change the value of the reference itself, rather than the value of its individual elements or fields.

Matrizes de parâmetrosParameter arrays

Às vezes, o requisito de que você especifique o número exato de argumentos para o método é restritivo.Sometimes, the requirement that you specify the exact number of arguments to your method is restrictive. Usando a palavra-chave params para indicar que um parâmetro é uma matriz de parâmetros, você permite que o método seja chamado com um número variável de argumentos.By using the params keyword to indicate that a parameter is a parameter array, you allow your method to be called with a variable number of arguments. O parâmetro marcado com a palavra-chave params deve ser um tipo de matriz e ele deve ser o último parâmetro na lista de parâmetros do método.The parameter tagged with the params keyword must be an array type, and it must be the last parameter in the method's parameter list.

Um chamador pode, então, invocar o método de uma das três maneiras:A caller can then invoke the method in either of three ways:

  • Passando uma matriz do tipo apropriado que contém o número de elementos desejado.By passing an array of the appropriate type that contains the desired number of elements.
  • Passando uma lista separada por vírgulas de argumentos individuais do tipo apropriado para o método.By passing a comma-separated list of individual arguments of the appropriate type to the method.
  • Não fornecendo um argumento para a matriz de parâmetros.By not providing an argument to the parameter array.

O exemplo a seguir define um método chamado GetVowels que retorna todas as vogais de uma matriz de parâmetros.The following example defines a method named GetVowels that returns all the vowels from a parameter array. O método Main ilustra todas as três maneiras de invocar o método.The Main method illustrates all three ways of invoking the method. Os chamadores não precisam fornecer argumentos para parâmetros que incluem o modificador params.Callers are not required to supply any arguments for parameters that include the params modifier. Nesse caso, o parâmetro é null.In that case, the parameter is null.

using System;
using System.Linq;

class Example
{
    static void Main()
    {
        string fromArray = GetVowels(new[] { "apple", "banana", "pear" });
        Console.WriteLine($"Vowels from array: '{fromArray}'");

        string fromMultipleArguments = GetVowels("apple", "banana", "pear");
        Console.WriteLine($"Vowels from multiple arguments: '{fromMultipleArguments}'");

        string fromNoValue = GetVowels();
        Console.WriteLine($"Vowels from no value: '{fromNoValue}'");
    }

    static string GetVowels(params string[] input)
    {
        if (input == null || input.Length == 0)
        {
            return string.Empty;
        }

        var vowels = new char[] { 'A', 'E', 'I', 'O', 'U' };
        return string.Concat(
            input.SelectMany(
                word => word.Where(letter => vowels.Contains(char.ToUpper(letter)))));
    }
}

// The example displays the following output:
//     Vowels from array: 'aeaaaea'
//     Vowels from multiple arguments: 'aeaaaea'
//     Vowels from no value: ''

Parâmetros e argumentos opcionaisOptional parameters and arguments

Uma definição de método pode especificar que os parâmetros são obrigatórios ou que são opcionais.A method definition can specify that its parameters are required or that they are optional. Por padrão, os parâmetros são obrigatórios.By default, parameters are required. Os parâmetros opcionais são especificados incluindo o valor padrão do parâmetro na definição do método.Optional parameters are specified by including the parameter's default value in the method definition. Quando o método for chamado, se nenhum argumento for fornecido para um parâmetro opcional, o valor padrão será usado em vez disso.When the method is called, if no argument is supplied for an optional parameter, the default value is used instead.

O valor padrão do parâmetro deve ser atribuído por um dos tipos de expressões a seguir:The parameter's default value must be assigned by one of the following kinds of expressions:

  • Uma constante, como um número ou uma cadeia de caracteres literal.A constant, such as a literal string or number.
  • Uma expressão da forma new ValType, em que ValType é um tipo de valor.An expression of the form new ValType, where ValType is a value type. Isso invoca o construtor sem parâmetros implícito do tipo de valor, que não é de fato um membro do tipo.Note that this invokes the value type's implicit parameterless constructor, which is not an actual member of the type.
  • Uma expressão da forma default(ValType), em que ValType é um tipo de valor.An expression of the form default(ValType), where ValType is a value type.

Se um método inclui parâmetros obrigatórios e opcionais, os parâmetros opcionais são definidos no final da lista de parâmetros, após todos os parâmetros obrigatórios.If a method includes both required and optional parameters, optional parameters are defined at the end of the parameter list, after all required parameters.

O exemplo a seguir define um método, ExampleMethod, que tem um parâmetro obrigatório e dois opcionais.The following example defines a method, ExampleMethod, that has one required and two optional parameters.

using System;

public class Options
{
   public void ExampleMethod(int required, int optionalInt = default(int),
                             string description = "Optional Description")
   {
      Console.WriteLine("{0}: {1} + {2} = {3}", description, required, 
                        optionalInt, required + optionalInt);
   }
}

Se um método com vários argumentos opcionais for invocado usando argumentos posicionais, o chamador deverá fornecer um argumento para todos os parâmetros opcionais do primeiro ao último para o qual um argumento é fornecido.If a method with multiple optional arguments is invoked using positional arguments, the caller must supply an argument for all optional parameters from the first one to the last one for which an argument is supplied. No caso do método ExampleMethod, por exemplo, se o chamador fornecer um argumento para o parâmetro description, ele deverá fornecer também um para o parâmetro optionalInt.In the case of the ExampleMethod method, for example, if the caller supplies an argument for the description parameter, it must also supply one for the optionalInt parameter. opt.ExampleMethod(2, 2, "Addition of 2 and 2"); é uma chamada de método válida, opt.ExampleMethod(2, , "Addition of 2 and 0"); gera um erro do compilador de “Argumento ausente”.opt.ExampleMethod(2, 2, "Addition of 2 and 2"); is a valid method call; opt.ExampleMethod(2, , "Addition of 2 and 0"); generates an "Argument missing" compiler error.

Se um método for chamado usando argumentos nomeados ou uma combinação de argumentos posicionais e nomeados, o chamador poderá omitir todos os argumentos após o último argumento posicional na chamada do método.If a method is called using named arguments or a combination of positional and named arguments, the caller can omit any arguments that follow the last positional argument in the method call.

A exemplo a seguir chama o método ExampleMethod três vezes.The following example calls the ExampleMethod method three times. As duas primeiras chamadas de método usam argumentos posicionais.The first two method calls use positional arguments. O primeiro omite ambos os argumentos opcionais, enquanto o segundo omite o último argumento.The first omits both optional arguments, while the second omits the last argument. A terceira chamada de método fornece um argumento posicional para o parâmetro obrigatório, mas usa um argumento nomeado para fornecer um valor para o parâmetro description enquanto omite o argumento optionalInt.The third method call supplies a positional argument for the required parameter, but uses a named argument to supply a value to the description parameter while omitting the optionalInt argument.

public class Example
{
   public static void Main()
   {
      var opt = new Options();
      opt.ExampleMethod(10);
      opt.ExampleMethod(10, 2);
      opt.ExampleMethod(12, description: "Addition with zero:");
   }
} 
// The example displays the following output:
//      Optional Description: 10 + 0 = 10
//      Optional Description: 10 + 2 = 12
//      Addition with zero:: 12 + 0 = 12

O uso de parâmetros opcionais afeta a resolução de sobrecarga ou a maneira em que o compilador C# determina qual sobrecarga específica deve ser invocada pela invocada de método, da seguinte maneira:The use of optional parameters affects overload resolution, or the way in which the C# compiler determines which particular overload should be invoked by a method call, as follows:

  • Um método, indexador ou construtor é um candidato para a execução se cada um dos parâmetros é opcional ou corresponde, por nome ou posição, a um único argumento na instrução de chamada e esse argumento pode ser convertido para o tipo do parâmetro.A method, indexer, or constructor is a candidate for execution if each of its parameters either is optional or corresponds, by name or by position, to a single argument in the calling statement, and that argument can be converted to the type of the parameter.
  • Se mais de um candidato for encontrado, as regras de resolução de sobrecarga de conversões preferenciais serão aplicadas aos argumentos que são especificados explicitamente.If more than one candidate is found, overload resolution rules for preferred conversions are applied to the arguments that are explicitly specified. Os argumentos omitidos para parâmetros opcionais são ignorados.Omitted arguments for optional parameters are ignored.
  • Se dois candidatos são considerados igualmente bons, a preferência vai para um candidato que não tem parâmetros opcionais para os quais argumentos foram omitidos na chamada.If two candidates are judged to be equally good, preference goes to a candidate that does not have optional parameters for which arguments were omitted in the call. Esta é uma consequência da preferência geral na resolução de sobrecarga de candidatos que têm menos parâmetros.This is a consequence of a general preference in overload resolution for candidates that have fewer parameters.

Valores de retornoReturn values

Os métodos podem retornar um valor para o chamador.Methods can return a value to the caller. 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 palavra-chave return.If the return type (the type listed before the method name) is not void, the method can return the value by using the return keyword. Uma instrução com a palavra-chave return seguida por uma variável, constante ou expressão que corresponde ao tipo de retorno retornará esse valor para o chamador do método.A statement with the return keyword followed by a variable, constant, or expression that matches the return type will return that value to the method caller. Métodos com um tipo de retorno não nulo devem usar a palavra-chave return para retornar um valor.Methods with a non-void return type are required to use the return keyword to return a value. A palavra-chave return também interrompe a execução do método.The return keyword also stops the execution of the method.

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.If the return type is void, a return statement without a value is still useful to stop the execution of the method. Sem a palavra-chave return, a execução do método será interrompida quando chegar ao final do bloco de código.Without the return keyword, the method will stop executing when it reaches the end of the code block.

Por exemplo, esses dois métodos usam a palavra-chave return para retornar inteiros:For example, these two methods use the return keyword to return integers:

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 a chamada de método em si em qualquer lugar que um valor do mesmo tipo seria suficiente.To use a value returned from a method, the calling method can use the method call itself anywhere a value of the same type would be sufficient. Você também pode atribuir o valor retornado a uma variável.You can also assign the return value to a variable. Por exemplo, os dois exemplos de código a seguir obtêm a mesma meta:For example, the following two code examples accomplish the same goal:

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);

Usar uma variável local, nesse caso, result, para armazenar um valor é opcional.Using a local variable, in this case, result, to store a value is optional. Isso pode ajudar a 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.It may help the readability of the code, or it may be necessary if you need to store the original value of the argument for the entire scope of the method.

Às vezes, você deseja que seu método retorne mais de um único valor.Sometimes, you want your method to return more than a single value. A partir do C# 7.0, você pode fazer isso facilmente usando tipos de tupla e literais de tupla.Starting with C# 7.0, you can do this easily by using tuple types and tuple literals. O tipo de tupla define os tipos de dados dos elementos da tupla.The tuple type defines the data types of the tuple's elements. Os literais de tupla fornecem os valores reais da tupla retornada.Tuple literals provide the actual values of the returned tuple. No exemplo a seguir, (string, string, string, int) define o tipo de tupla que é retornado pelo método GetPersonalInfo.In the following example, (string, string, string, int) defines the tuple type that is returned by the GetPersonalInfo method. A expressão (per.FirstName, per.MiddleName, per.LastName, per.Age) é a tupla literal, o método retorna o nome, o nome do meio e o sobrenome, juntamente com a idade, de um objeto PersonInfo.The expression (per.FirstName, per.MiddleName, per.LastName, per.Age) is the tuple literal; the method returns the first, middle, and last name, along with the age, of a PersonInfo object.

public (string, string, string, int) GetPersonalInfo(string id)
{
    PersonInfo per = PersonInfo.RetrieveInfoById(id);
    return (per.FirstName, per.MiddleName, per.LastName, per.Age);
}

O chamador pode então consumir a tupla retornada com o código semelhante ao seguinte:The caller can then consume the returned tuple with code like the following:

var person = GetPersonalInfo("111111111")
Console.WriteLine("{person.Item1} {person.Item3}: age = {person.Item4}");

Os nomes também podem ser atribuídos aos elementos da tupla na definição de tipo de tupla.Names can also be assigned to the tuple elements in the tuple type definition. O exemplo a seguir mostra uma versão alternativa do método GetPersonalInfo que usa elementos nomeados:The following example shows an alternate version of the GetPersonalInfo method that uses named elements:

public (string FName, string MName, string LName, int Age) GetPersonalInfo(string id)
{
    PersonInfo per = PersonInfo.RetrieveInfoById(id);
    return (per.FirstName, per.MiddleName, per.LastName, per.Age);
}

A chamada anterior para o método GetPersonInfo pode ser modificada da seguinte maneira:The previous call to the GetPersonInfo method can then be modified as follows:

var person = GetPersonalInfo("111111111");
Console.WriteLine("{person.FName} {person.LName}: age = {person.Age}");

Se um método passa uma matriz como um argumento e modifica o valor de elementos individuais, o método não precisa retornar a matriz, embora você possa optar por fazer isso para obter um bom estilo ou um fluxo de valores funcional.If a method is passed an array as an argument and modifies the value of individual elements, it is not necessary for the method to return the array, although you may choose to do so for good style or functional flow of values. Isso ocorre 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.This is because C# passes all reference types by value, and the value of an array reference is the pointer to the array. No exemplo a seguir, as alterações no conteúdo da matriz values realizados pelo método DoubleValues são observáveis por qualquer código que faz referência à matriz.In the following example, changes to the contents of the values array that are made in the DoubleValues method are observable by any code that has a reference to the array.



using System;

public class Example
{
   static void Main(string[] args)  
   {  
      int[] values = { 2, 4, 6, 8 };
      DoubleValues(values);
      foreach (var value in values)
         Console.Write("{0}  ", value);
   }  
  
   public static void DoubleValues(int[] arr)
   {
      for (int ctr = 0; ctr <= arr.GetUpperBound(0); ctr++)
         arr[ctr] = arr[ctr] * 2;
   }
}
// The example displays the following output:
//       4  8  12  16

Métodos de extensãoExtension methods

Normalmente, há duas maneiras de adicionar um método a um tipo existente:Ordinarily, there are two ways to add a method to an existing type:

  • Modificar o código-fonte para esse tipo.Modify the source code for that type. Você não pode fazer isso, é claro, se não possui o código-fonte do tipo.You cannot do this, of course, if you do not own the type's source code. E isso se torna uma alteração significativa se você também adicionar campos de dados privados para dar suporte ao método.And this becomes a breaking change if you also add any private data fields to support the method.
  • Definir o novo método em uma classe derivada.Define the new method in a derived class. Não é possível adicionar um método dessa forma usando a herança para outros tipos, como estruturas e enumerações.A method cannot be added in this way using inheritance for other types, such as structures and enumerations. Isso também não pode ser usado para “adicionar” um método a uma classe selada.Nor can it be used to "add" a method to a sealed class.

Os métodos de extensão permitem que você “adicione” um método a um tipo existente sem modificar o tipo em si ou implementar o novo método em um tipo herdado.Extension methods let you "add" a method to an existing type without modifying the type itself or implementing the new method in an inherited type. O método de extensão também não precisa residir no mesmo assembly que o tipo que ele estende.The extension method also does not have to reside in the same assembly as the type it extends. Você chama um método de extensão como se fosse um membro definido de um tipo.You call an extension method as if it were a defined member of a type.

Para obter mais informações, consulte Métodos de extensão.For more information, see Extension Methods.

Métodos assíncronosAsync Methods

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.By using the async feature, you can invoke asynchronous methods without using explicit callbacks or manually splitting your code across multiple methods or lambda expressions.

Se marcar um método com o modificador async, você poderá usar o operador await no método.If you mark a method with the async modifier, you can use the await operator in the method. Quando o controle atingir uma expressão await no método assíncrono, o controle retornará para o chamador se a tarefa aguardada não estiver concluída e o progresso no método com a palavra-chave await será suspenso até a tarefa aguardada ser concluída.When control reaches an await expression in the async method, control returns to the caller if the awaited task is not completed, and progress in the method with the await keyword is suspended until the awaited task completes. Quando a tarefa for concluída, a execução poderá ser retomada no método.When the task is complete, execution can resume in the method.

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.An async method returns to the caller when either it encounters the first awaited object that’s not yet complete or it gets to the end of the async method, whichever occurs first.

Um método assíncrono pode ter um tipo de retorno Task<TResult>, Task ou void.An async method can have a return type of Task<TResult>, Task, or void. O tipo de retorno void é usado principalmente para definir manipuladores de eventos, nos quais o tipo de retorno void é necessário.The void return type is used primarily to define event handlers, where a void return type is required. 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.An async method that returns void can't be awaited, and the caller of a void-returning method can't catch exceptions that the method throws. Começando com o C# 7.0, um método assíncrono pode ter qualquer tipo de retorno como os de tarefa.Starting with C# 7.0, an async method can have any task-like return type.

No exemplo a seguir, DelayAsync é um método assíncrono que contém uma instrução return que retorna um inteiro.In the following example, DelayAsync is an async method that has a return statement that returns an integer. Como é um método assíncrono, sua declaração de método deve ter um tipo de retorno de Task<int>.Because it is an async method, its method declaration must have a return type of Task<int>. Como o tipo de retorno é Task<int>, a avaliação da expressão await em DoSomethingAsync produz um inteiro, como a instrução int result = await delayTask a seguir demonstra.Because the return type is Task<int>, the evaluation of the await expression in DoSomethingAsync produces an integer, as the following int result = await delayTask statement demonstrates.

using System;
using System.Diagnostics;
using System.Threading.Tasks;

public class Example
{
    // This Click event is marked with the async modifier.
    public static void Main()
    {
       DoSomethingAsync().Wait();
    }

    private static async Task DoSomethingAsync()
    {
        int result = await DelayAsync();
        Console.WriteLine("Result: " + result);
    }

    private static async Task<int> DelayAsync()
    {
        await Task.Delay(100);
        return 5;
    }

    // Output:
    //  Result: 5
}
// The example displays the following output:
//        Result: 5

Um método assíncrono não pode declarar os parâmetros in, ref nem out, mas pode chamar métodos que tenham esses parâmetros.An async method can't declare any in, ref, or out parameters, but it can call methods that have such parameters.

Para obter mais informações sobre os métodos assíncronos, consulte Programação assíncrona com async e await, Fluxo de controle em programas assíncronos e Tipos de retorno assíncronos.For more information about async methods, see Asynchronous Programming with Async and Await, Control Flow in Async Programs, and Async Return Types.

Membros aptos para expressãoExpression-bodied members

É comum ter definições de método que simplesmente retornam imediatamente com o resultado de uma expressão ou que têm uma única instrução como o corpo do método.It is common to have method definitions that simply return immediately with the result of an expression, or that have a single statement as the body of the method. Há um atalho de sintaxe para definir esses métodos usando =>:There is a syntax shortcut for defining such methods using =>:

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 aos lambdas).If the method returns void or is an async method, the body of the method must be a statement expression (same as with lambdas). Para propriedades e indexadores, eles devem ser somente leitura e não usar a palavra-chave do acessador get.For properties and indexers, they must be read-only, and you do not use the get accessor keyword.

IteratorsIterators

Um iterador realiza uma iteração personalizada em uma coleção, como uma lista ou uma matriz.An iterator performs a custom iteration over a collection, such as a list or an array. Um iterador usa a instrução yield return para retornar um elemento de cada vez.An iterator uses the yield return statement to return each element one at a time. Quando uma instrução yield return for atingida, o local atual será lembrado para que o chamador possa solicitar o próximo elemento na sequência.When a yield return statement is reached, the current location is remembered so that the caller can request the next element in the sequence.

O tipo de retorno de um iterador pode ser IEnumerable, IEnumerable<T>, IEnumerator ou IEnumerator<T>.The return type of an iterator can be IEnumerable, IEnumerable<T>, IEnumerator, or IEnumerator<T>.

Para obter mais informações, consulte Iteradores.For more information, see Iterators.

Consulte tambémSee also