MetodiMethods

Un metodo è un blocco di codice che contiene una serie di istruzioni.A method is a code block that contains a series of statements. Un programma fa in modo che le istruzioni vengano eseguite chiamando il metodo e specificando gli argomenti del metodo obbligatori.A program causes the statements to be executed by calling the method and specifying any required method arguments. In C#, ogni istruzione eseguita viene attuata nel contesto di un metodo.In C#, every executed instruction is performed in the context of a method. Il metodo Main è il punto di ingresso per ogni applicazione C# e viene chiamato da Common Language Runtime (CLR) quando viene avviato il programma.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.

Nota

In questo argomento vengono descritti i metodi denominati.This topic discusses named methods. Per informazioni sulle funzioni anonime, vedere Funzioni anonime.For information about anonymous functions, see Anonymous Functions.

Di seguito sono elencate le diverse sezioni di questo argomento:This topic contains the following sections:

Firme del metodoMethod signatures

I metodi vengono dichiarati in class o struct specificando:Methods are declared in a class or struct by specifying:

  • Un livello di accesso facoltativo, ad esempio public o private.An optional access level, such as public or private. Il valore predefinito è private.The default is private.
  • Modificatori facoltativi, ad esempio abstract o sealed.Optional modifiers such as abstract or sealed.
  • Il valore restituito o void se il metodo non ha alcun valore.The return value, or void if the method has none.
  • Nome del metodo.The method name.
  • Tutti i parametri del metodo.Any method parameters. I parametri del metodo vengono racchiusi tra parentesi e separati da virgole.Method parameters are enclosed in parentheses and are separated by commas. Le parentesi vuote indicano che il metodo non richiede parametri.Empty parentheses indicate that the method requires no parameters.

Queste parti costituiscono la firma del metodo.These parts together form the method signature.

Nota

Un tipo restituito di un metodo non fa parte della firma del metodo in caso di overload dei metodi.A return type of a method is not part of the signature of the method for the purposes of method overloading. Fa tuttavia parte della firma del metodo quando si determina la compatibilità tra un delegato e il metodo a cui fa riferimento.However, it is part of the signature of the method when determining the compatibility between a delegate and the method that it points to.

L'esempio seguente definisce una classe denominata Motorcycle che contiene cinque metodi: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(); 
}

Si noti che la classe Motorcycle include un metodo sottoposto a overload, ovvero Drive.Note that the Motorcycle class includes an overloaded method, Drive. Due metodi hanno lo stesso nome, ma devono essere differenziati in base ai relativi tipi di parametri.Two methods have the same name, but must be differentiated by their parameter types.

Chiamata del metodoMethod invocation

I metodi possono essere di istanza o statici.Methods can be either instance or static. Per chiamare un metodo di istanza è necessario creare un'istanza di un oggetto e chiamare il metodo nell'oggetto; un metodo di istanza agisce sull'istanza e i relativi dati.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. La chiamata a un metodo statico viene eseguita facendo riferimento al nome del tipo a cui appartiene il metodo; i metodi statici non agiscono sui dati dell'istanza.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. Se si tenta di chiamare un metodo statico attraverso un'istanza di un oggetto viene generato un errore del compilatore.Attempting to call a static method through an object instance generates a compiler error.

La chiamata a un metodo è un'operazione analoga all'accesso a un campo.Calling a method is like accessing a field. Dopo il nome dell'oggetto (in una chiamata a un metodo di istanza) o il nome del tipo (in una chiamata a un metodo static), aggiungere un punto, il nome del metodo e le parentesi.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. Gli argomenti vengono elencati tra parentesi e separati da virgole.Arguments are listed within the parentheses, and are separated by commas.

La definizione del metodo specifica i nomi e i tipi di tutti i parametri obbligatori.The method definition specifies the names and types of any parameters that are required. Quando il chiamante chiama il metodo, specifica valori concreti, chiamati argomenti, per ogni parametro.When a caller invokes the method, it provides concrete values, called arguments, for each parameter. Gli argomenti devono essere compatibili con il tipo di parametro, ma il nome dell'argomento, se usato nel codice chiamante, non deve essere lo stesso del parametro denominato definito nel metodo.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. Nell'esempio seguente il metodo Square include un singolo parametro di tipo int denominato i.In the following example, the Square method includes a single parameter of type int named i. La prima chiamata al metodo passa al metodo Square una variabile di tipo int denominata num, la seconda passa una costante numerica e la terza passa un'espressione.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;
   }
}

La forma più comune di chiamata al metodo usa argomenti posizionali; specifica gli argomenti nello stesso ordine dei parametri del metodo.The most common form of method invocation used positional arguments; it supplies arguments in the same order as method parameters. Per questa ragione, i metodi della classe Motorcycle possono essere chiamati come nell'esempio seguente.The methods of the Motorcycle class can therefore be called as in the following example. La chiamata al metodo Drive, ad esempio, include due argomenti che corrispondono ai due parametri nella sintassi del metodo.The call to the Drive method, for example, includes two arguments that correspond to the two parameters in the method's syntax. Il primo diventa il valore del parametro miles, il secondo il valore del parametro 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);            
   }
}

Quando si esegue una chiamata a un metodo è anche possibile usare argomenti denominati anziché argomenti posizionali.You can also used named arguments instead of positional arguments when invoking a method. Quando si usano gli argomenti denominati, si specifica il nome del parametro seguito da due punti (":") e l'argomento.When using named arguments, you specify the parameter name followed by a colon (":") and the argument. Gli argomenti del metodo possono essere in qualsiasi ordine, a condizione che siano presenti tutti gli argomenti necessari.Arguments to the method can appear in any order, as long as all required arguments are present. L'esempio seguente usa gli argomenti denominati per richiamare il metodo TestMotorcycle.Drive.The following example uses named arguments to invoke the TestMotorcycle.Drive method. In questo esempio gli argomenti denominati vengono passati nell'ordine inverso dall'elenco di parametri del metodo.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

È possibile richiamare un metodo usando argomenti posizionali e denominati.You can invoke a method using both positional arguments and named arguments. Un argomento posizionale non può, tuttavia, seguire un argomento denominato.However, a positional argument cannot follow a named argument. L'esempio seguente richiama il metodo TestMotorcycle.Drive dall'esempio precedente usando un argomento posizionale e un argomento denominato.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);

Metodi ereditati e sottoposti a overrideInherited and overridden methods

Oltre ai membri definiti in modo esplicito in un tipo, un tipo eredita i membri definiti nelle relative classi base.In addition to the members that are explicitly defined in a type, a type inherits members defined in its base classes. Poiché tutti i tipi del sistema di tipi gestiti ereditano direttamente o indirettamente dalla classe Object, tutti i tipi di ereditano i relativi membri, ad esempio 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(). L'esempio seguente definisce una classe Person, crea l'istanza di due oggetti Person e chiama il metodo Person.Equals per determinare se i due oggetti sono uguali.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. Il metodo Equals, tuttavia, non è definito nella classe Person; viene ereditato da 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

I tipi possono eseguire l'override dei membri ereditati usando la parola chiave override e specificando un'implementazione per il metodo sottoposto a override.Types can override inherited members by using the override keyword and providing an implementation for the overridden method. La firma del metodo deve essere la stessa del metodo sottoposto a override.The method signature must be the same as that of the overridden method. L'esempio seguente è simile a quello precedente, ad eccezione del fatto che viene eseguito l'override del metodo Equals(Object).The following example is like the previous one, except that it overrides the Equals(Object) method. Viene anche eseguito l'override del metodo GetHashCode() poiché i due metodi devono fornire risultati coerenti.(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

Passaggio di parametriPassing parameters

I tipi in C# sono tipi di valore o tipi di riferimento.Types in C# are either value types or reference types. Per un elenco dei tipi di valore predefiniti, vedere Tipi e variabili.For a list of built-in value types, see Types and variables. Per impostazione predefinita, i tipi di valore e i tipi di riferimento vengono passati a un metodo per valore.By default, both value types and reference types are passed to a method by value.

Passaggio di parametri per valorePassing parameters by value

Quando un tipo valore viene passato a un metodo per valore, viene passata al metodo una copia dell'oggetto anziché l'oggetto stesso.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. Di conseguenza, le modifiche all'oggetto nel metodo chiamato non hanno effetto sull'oggetto originale quando il controllo torna al chiamante.Therefore, changes to the object in the called method have no effect on the original object when control returns to the caller.

L'esempio seguente passa un tipo di valore a un metodo per valore e il metodo chiamato tenta di modificare il valore del tipo di valore.The following example passes a value type to a method by value, and the called method attempts to change the value type's value. Definisce una variabile di tipo int, che è un tipo di valore, ne inizializza il valore a 20 e la passa a un metodo denominato ModifyValue che modifica il valore della variabile in 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. Quando il metodo viene restituito, tuttavia, il valore della variabile rimane invariato.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 viene passato un oggetto di tipo riferimento a un metodo per valore, viene passato un riferimento all'oggetto per valore,When an object of a reference type is passed to a method by value, a reference to the object is passed by value. ovvero il metodo riceve un argomento che indica la posizione dell'oggetto, ma non l'oggetto stesso.That is, the method receives not the object itself, but an argument that indicates the location of the object. Se si modifica un membro dell'oggetto usando questo riferimento, la modifica si riflette nell'oggetto quando il controllo torna al metodo chiamante.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. Tuttavia, la sostituzione dell'oggetto passato al metodo non ha effetto sull'oggetto originale quando il controllo torna al chiamante.However, replacing the object passed to the method has no effect on the original object when control returns to the caller.

L'esempio seguente definisce una classe (che è un tipo riferimento) denominata SampleRefType.The following example defines a class (which is a reference type) named SampleRefType. Crea un'istanza di un oggetto SampleRefType, assegna 44 al campo value e passa l'oggetto al metodo ModifyObject.It instantiates a SampleRefType object, assigns 44 to its value field, and passes the object to the ModifyObject method. L'esempio è sostanzialmente uguale al precedente in quanto passa un argomento per valore a un metodoThis example does essentially the same thing as the previous example -- it passes an argument by value to a method. ma, essendo usato un tipo riferimento, il risultato è diverso.But because a reference type is used, the result is different. La modifica eseguita in ModifyObject al campo obj.value cambia anche il campo value dell'argomento rt nel metodo Main in 33, come mostra l'output dell'esempio.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;
    }
}

Passaggio di parametri per riferimentoPassing parameters by reference

È necessario passare un parametro per riferimento quando si vuole modificare il valore di un argomento in un metodo e questa modifica deve essere applicata quando il controllo torna al metodo chiamante.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. Per passare un parametro per riferimento, usare la parola chiave ref o out.To pass a parameter by reference, you use the ref or out keyword. È anche possibile passare un valore per riferimento per evitare la copia, ma comunque impedire modifiche usando la parola chiave in.You can also pass a value by reference to avoid copying but still prevent modifications using the in keyword.

L'esempio seguente è identico a quello precedente, ad eccezione del fatto che il valore viene passato per riferimento al metodo ModifyValue.The following example is identical to the previous one, except the value is passed by reference to the ModifyValue method. Quando il valore del parametro è modificato nel metodo ModifyValue, la modifica del valore si riflette quando il controllo torna al chiamante.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

Un modello comune che usa parametri di riferimento implica lo scambio dei valori delle variabili.A common pattern that uses by ref parameters involves swapping the values of variables. Si passano due variabili a un metodo per riferimento e il metodo scambia il loro contenuto.You pass two variables to a method by reference, and the method swaps their contents. L'esempio seguente scambia i valori integer.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

Il passaggio di un parametro di tipo riferimento consente di modificare il valore del riferimento stesso anziché il valore dei singoli elementi o campi.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.

Matrici di parametriParameter arrays

In alcuni casi, il requisito che richiede di specificare il numero esatto di argomenti per il metodo è limitativo.Sometimes, the requirement that you specify the exact number of arguments to your method is restrictive. Usando la parola chiave params per indicare che un parametro è una matrice di parametri, si consente la chiamata al metodo con un numero variabile di argomenti.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. Il parametro contrassegnato con la parola chiave params deve essere di tipo matrice e deve essere l'ultimo parametro dell'elenco di parametri del metodo.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.

Un chiamante potrà quindi richiamare il metodo in uno dei tre modi seguenti:A caller can then invoke the method in either of three ways:

  • Passando una matrice del tipo appropriato che contiene il numero desiderato di elementi.By passing an array of the appropriate type that contains the desired number of elements.
  • Passando un elenco delimitato da virgole di singoli argomenti del tipo appropriato al metodo.By passing a comma-separated list of individual arguments of the appropriate type to the method.
  • Non specificando un argomento nella matrice di parametri.By not providing an argument to the parameter array.

L'esempio seguente definisce un metodo denominato GetVowels che restituisce tutte le vocali da una matrice di parametri.The following example defines a method named GetVowels that returns all the vowels from a parameter array. Il metodo Main illustra tutti e tre i metodi di chiamata al metodo.The Main method illustrates all three ways of invoking the method. Non è necessario che i chiamanti specifichino un argomento per i parametri che includono il modificatore params.Callers are not required to supply any arguments for parameters that include the params modifier. In questo caso, il parametro è 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: ''

Parametri e argomenti facoltativiOptional parameters and arguments

La definizione di un metodo può specificare che i parametri sono obbligatori o facoltativi.A method definition can specify that its parameters are required or that they are optional. I parametri sono obbligatori per impostazione predefinita.By default, parameters are required. I parametri facoltativi vengono specificati includendo il valore predefinito del parametro nella definizione del metodo.Optional parameters are specified by including the parameter's default value in the method definition. Quando il metodo viene chiamato, se non sono specificati argomenti per un parametro facoltativo, viene usato il valore predefinito.When the method is called, if no argument is supplied for an optional parameter, the default value is used instead.

Il valore predefinito del parametro deve essere assegnato da uno dei tipi di espressioni seguenti:The parameter's default value must be assigned by one of the following kinds of expressions:

  • Una costante, ad esempio una stringa letterale o un numero.A constant, such as a literal string or number.
  • Un'espressione del form new ValType, dove ValType è un tipo di valore.An expression of the form new ValType, where ValType is a value type. Osservare come venga richiamato il costruttore senza parametri implicito del tipo di valore, che non è un membro effettivo del tipo.Note that this invokes the value type's implicit parameterless constructor, which is not an actual member of the type.
  • Un'espressione del form default(ValType), dove ValType è un tipo di valore.An expression of the form default(ValType), where ValType is a value type.

Se un metodo include parametri obbligatori e facoltativi, i parametri facoltativi sono definiti alla fine dell'elenco di parametri, dopo tutti i parametri obbligatori.If a method includes both required and optional parameters, optional parameters are defined at the end of the parameter list, after all required parameters.

L'esempio seguente definisce un metodo, ExampleMethod, con un parametro obbligatorio e due facoltativi.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 viene richiamato un metodo con più argomenti facoltativi usando argomenti posizionali, il chiamante deve specificare un argomento per tutti i parametri facoltativi, dal primo all'ultimo parametro per il quale è specificato un argomento.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. Nel caso del metodo ExampleMethod, ad esempio, se il chiamante specifica un argomento per il parametro description, deve specificarne uno anche per il parametro 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"); è una chiamata a un metodo valido; opt.ExampleMethod(2, , "Addition of 2 and 0"); genera un errore di compilazione "Argomento mancante".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 un metodo viene chiamato usando argomenti denominati o una combinazione di argomenti posizionali e denominati, il chiamante può omettere tutti gli argomenti successivi all'ultimo argomento posizionale nella chiamata al metodo.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.

L'esempio seguente esegue una chiamata al metodo ExampleMethod tre volte.The following example calls the ExampleMethod method three times. Le prime due chiamate al metodo usano argomenti posizionali.The first two method calls use positional arguments. La prima omette entrambi gli argomenti facoltativi, mentre la seconda omette l'ultimo argomento.The first omits both optional arguments, while the second omits the last argument. La terza chiamata al metodo specifica un argomento posizionale per il parametro obbligatorio, ma usa un argomento denominato per specificare un valore per il parametro description omettendo l'argomento 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

L'uso di parametri facoltativi ha effetto sulla risoluzione dell'overload o sulla modalità con la quale il compilatore C# determina l'overload specifico da richiamare tramite una chiamata al metodo come descritto di seguito: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:

  • Un metodo, un indicizzatore o un costruttore è un candidato per l'esecuzione se ogni parametro è facoltativo o corrisponde, per nome o per posizione, a un solo argomento nell'istruzione chiamante e tale argomento può essere convertito nel tipo del parametro.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 è disponibile più di un candidato, agli argomenti specificati in modo esplicito vengono applicate le regole di risoluzione dell'overload per le conversioni preferite.If more than one candidate is found, overload resolution rules for preferred conversions are applied to the arguments that are explicitly specified. Gli argomenti omessi per i parametri facoltativi vengono ignorati.Omitted arguments for optional parameters are ignored.
  • Se due candidati sono giudicati ugualmente validi, la preferenza va a un candidato che non ha parametri facoltativi per i quali sono stati omessi gli argomenti nella chiamata.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. Si tratta di una conseguenza di una preferenza generale nella risoluzione dell'overload per i candidati che hanno un numero di parametri inferiore.This is a consequence of a general preference in overload resolution for candidates that have fewer parameters.

Valori restituitiReturn values

I metodi possono restituire un valore al chiamante.Methods can return a value to the caller. Se il tipo restituito, ovvero il tipo elencato prima del nome del metodo, non è void, il metodo può restituire il valore usando la parola chiave 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. Un'istruzione con la parola chiave return seguita da una variabile, una costante o un'espressione corrispondente al tipo restituito restituirà tale valore al chiamante del metodo.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. Per usare la parola chiave return per restituire un valore, sono obbligatori metodi con un tipo restituito non void.Methods with a non-void return type are required to use the return keyword to return a value. La parola chiave return interrompe anche l'esecuzione del metodo.The return keyword also stops the execution of the method.

Se il tipo restituito è void, un'istruzione return senza un valore è tuttavia utile per interrompere l'esecuzione del metodo.If the return type is void, a return statement without a value is still useful to stop the execution of the method. Senza la parola chiave return , l'esecuzione del metodo verrà interrotta quando verrà raggiunta la fine del blocco di codice.Without the return keyword, the method will stop executing when it reaches the end of the code block.

Ad esempio, questi due metodi usano la parola chiave return per restituire numeri interi: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;
    }
}

Per usare un valore restituito da un metodo, il metodo chiamante può usare la chiamata al metodo stessa ovunque è sufficiente un valore dello stesso tipo.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. È inoltre possibile assegnare il valore restituito a una variabile.You can also assign the return value to a variable. I due esempi seguenti di codice ottengono lo stesso risultato: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);

L'uso di una variabile locale, in questo caso result, per archiviare un valore è facoltativo.Using a local variable, in this case, result, to store a value is optional. Potrebbe migliorare la leggibilità del codice o potrebbe essere necessario se si desidera archiviare il valore originale dell'argomento per l'intero ambito del metodo.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.

In alcuni casi, si vuole che il metodo restituisca più di un singolo valore.Sometimes, you want your method to return more than a single value. A questo scopo, a partire da C# 7.0 è possibile usare tipi di tupla e letterali di tupla.Starting with C# 7.0, you can do this easily by using tuple types and tuple literals. Il tipo di tupla definisce i tipi di dati degli elementi della tupla.The tuple type defines the data types of the tuple's elements. I letterali di tupla specificano i valori effettivi della tupla restituita.Tuple literals provide the actual values of the returned tuple. Nell'esempio seguente (string, string, string, int) definisce il tipo di tupla restituito dal metodo GetPersonalInfo.In the following example, (string, string, string, int) defines the tuple type that is returned by the GetPersonalInfo method. L'espressione (per.FirstName, per.MiddleName, per.LastName, per.Age) è il letterale della tupla; il metodo restituisce il nome iniziale, centrale e finale e la durata di un oggetto 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);
}

Il chiamante può quindi usare la tupla restituita con codice simile al seguente: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}");

È anche possibile assegnare i nomi agli elementi della tupla nella definizione del tipo della tupla.Names can also be assigned to the tuple elements in the tuple type definition. L'esempio seguente mostra una versione alternativa del metodo GetPersonalInfo che usa elementi denominati: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);
}

La chiamata precedente al metodo GetPersonInfo può quindi essere modificata come segue: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 a un metodo viene passata una matrice come argomento e il metodo modifica il valore dei singoli elementi, non è necessario che il metodo restituisca la matrice, anche se è possibile scegliere di effettuare questa operazione per ragioni di stile o per il flusso funzionale di valori.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. L'operazione non è necessaria perché C# passa tutti i tipi riferimento per valore e il valore di un riferimento a una matrice è il puntatore alla matrice.This is because C# passes all reference types by value, and the value of an array reference is the pointer to the array. Nell'esempio seguente le modifiche al contenuto della matrice values eseguite nel metodo DoubleValues sono rilevabili da qualsiasi codice che include un riferimento alla matrice.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

Metodi di estensioneExtension methods

In genere, è possibile aggiungere un metodo a un tipo esistente in due modi:Ordinarily, there are two ways to add a method to an existing type:

  • Modificare il codice sorgente per il tipo.Modify the source code for that type. Questa operazione non è possibile se non si è proprietari del codice sorgente del tipo.You cannot do this, of course, if you do not own the type's source code. Questa operazione diventa una modifica importante se si aggiungono anche tutti i campi dati privati per supportare il metodo.And this becomes a breaking change if you also add any private data fields to support the method.
  • Definire il nuovo metodo in una classe derivata.Define the new method in a derived class. Non è possibile aggiungere un metodo in questo modo usando l'ereditarietà per gli altri tipi, ad esempio strutture ed enumerazioni.A method cannot be added in this way using inheritance for other types, such as structures and enumerations. Questo modo non può essere usato neanche per "aggiungere" un metodo a una classe sealed.Nor can it be used to "add" a method to a sealed class.

I metodi di estensione consentono di "aggiungere" un metodo a un tipo esistente senza modificare il tipo o implementare il nuovo metodo in un tipo ereditato.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. È necessario anche che il metodo di estensione non si trovi nello stesso assembly del tipo che estende.The extension method also does not have to reside in the same assembly as the type it extends. Un metodo di estensione viene chiamato come se fosse un membro definito di un tipo.You call an extension method as if it were a defined member of a type.

Per altre informazioni, vedere Metodi di estensione.For more information, see Extension Methods.

Metodi asincroniAsync Methods

Tramite la funzionalità async, è possibile richiamare i metodi asincroni senza usare callback espliciti o suddividere manualmente il codice in più metodi o espressioni 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 si contrassegna un metodo con il modificatore async, è possibile usare l'operatore await nel metodo.If you mark a method with the async modifier, you can use the await operator in the method. Quando il controllo raggiunge un'espressione await nel metodo asincrono, il controllo torna al chiamante se l'attività attesa non è stata completata e l'avanzamento nel metodo con la parola chiave await viene sospeso fino al completamento dell'attività attesa.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. Una volta completata l'attività, l'esecuzione del metodo può riprendere.When the task is complete, execution can resume in the method.

Nota

Un metodo async viene restituito al chiamante quando rileva il primo oggetto atteso che non è ancora completo o raggiunge la fine del metodo async, qualunque si verifichi prima.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.

Un metodo asincrono può avere un tipo restituito Task<TResult>, Task o void.An async method can have a return type of Task<TResult>, Task, or void. Il tipo restituito void viene usato principalmente per definire i gestori eventi in cui è necessario un tipo restituito void.The void return type is used primarily to define event handlers, where a void return type is required. Un metodo asincrono che restituisce void non può essere atteso e il chiamante di un metodo che restituisce void non può intercettare le eccezioni generate dal metodo.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. A partire da C# 7.0, un metodo asincrono può avere qualsiasi tipo restituito di tipo attività.Starting with C# 7.0, an async method can have any task-like return type.

Nell'esempio seguente DelayAsync è un metodo asincrono con un'istruzione return che restituisce un valore Integer.In the following example, DelayAsync is an async method that has a return statement that returns an integer. Poiché si tratta di un metodo asincrono, la dichiarazione del metodo deve avere un tipo restituito di Task<int>.Because it is an async method, its method declaration must have a return type of Task<int>. Poiché il tipo restituito è Task<int>, la valutazione dell'espressione await in DoSomethingAsync genera un numero intero come dimostra l'istruzione int result = await delayTask seguente.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

Un metodo asincrono non può dichiarare parametri in, ref o out, ma può chiamare metodi che hanno tali parametri.An async method can't declare any in, ref, or out parameters, but it can call methods that have such parameters.

Per altre informazioni sui metodi asincroni, vedere Programmazione asincrona con Async e Await, Flusso di controllo in programmi asincroni e Tipi restituiti asincroni.For more information about async methods, see Asynchronous Programming with Async and Await, Control Flow in Async Programs, and Async Return Types.

Membri con corpo di espressioneExpression-bodied members

È comune disporre di definizioni di metodo che semplicemente restituiscono subito il risultato di un'espressione o che includono una singola istruzione come corpo del metodo.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. Esiste una sintassi breve per definire tali metodi 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 il metodo restituisce void o è un metodo asincrono, il corpo del metodo deve essere un'espressione di istruzione (come per le espressioni lambda).If the method returns void or is an async method, the body of the method must be a statement expression (same as with lambdas). Le proprietà e gli indicizzatori devono essere di sola lettura e non è necessario usare la parola chiave della funzione di accesso get .For properties and indexers, they must be read-only, and you do not use the get accessor keyword.

IteratorsIterators

Un iteratore esegue un'iterazione personalizzata su una raccolta, ad esempio un elenco o una matrice.An iterator performs a custom iteration over a collection, such as a list or an array. Un iteratore usa l'istruzione yield return per restituire un elemento alla volta.An iterator uses the yield return statement to return each element one at a time. Quando viene raggiunta un'istruzione yield return, viene memorizzata la posizione corrente in modo che il chiamante possa richiedere l'elemento successivo della sequenza.When a yield return statement is reached, the current location is remembered so that the caller can request the next element in the sequence.

Il tipo restituito di un iteratore può essere IEnumerable, IEnumerable<T>, IEnumeratoro IEnumerator<T>.The return type of an iterator can be IEnumerable, IEnumerable<T>, IEnumerator, or IEnumerator<T>.

Per altre informazioni, vedere Iteratori.For more information, see Iterators.

Vedere ancheSee also