Formazione
Modulo
Creare metodi C# che restituiscono valori - Training
Questo modulo descrive la parola chiave return e la restituzione di valori dai metodi.
Questo browser non è più supportato.
Esegui l'aggiornamento a Microsoft Edge per sfruttare i vantaggi di funzionalità più recenti, aggiornamenti della sicurezza e supporto tecnico.
Un metodo è un blocco di codice che contiene una serie di istruzioni. Un programma fa in modo che le istruzioni vengano eseguite chiamando il metodo e specificando gli argomenti del metodo obbligatori. In C#, ogni istruzione eseguita viene attuata nel contesto di un metodo.
Nota
In questo argomento vengono descritti i metodi denominati. Per informazioni sulle funzioni anonime, consultare Espressioni lambda.
I metodi vengono dichiarati in class
, record
o struct
specificando:
public
o private
. Il valore predefinito è private
.abstract
o sealed
.void
se il metodo non ha alcun valore.Queste parti costituiscono la firma del metodo.
Importante
Un tipo restituito di un metodo non fa parte della firma del metodo in caso di overload dei metodi. Fa tuttavia parte della firma del metodo quando si determina la compatibilità tra un delegato e il metodo a cui fa riferimento.
L'esempio seguente definisce una classe denominata Motorcycle
che contiene cinque metodi:
namespace MotorCycleExample
{
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();
}
La classe Motorcycle
include un metodo sottoposto a overload, ovvero Drive
. Due metodi hanno lo stesso nome, ma sono differenziati in base ai relativi tipi di parametri.
I metodi possono essere di istanza o statici. È necessario creare un'istanza di un oggetto per chiamare un metodo di istanza nell'istanza; un metodo di istanza agisce sull'istanza e i relativi dati. 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. Se si tenta di chiamare un metodo statico attraverso un'istanza di un oggetto viene generato un errore del compilatore.
La chiamata a un metodo è un'operazione analoga all'accesso a un campo. 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. Gli argomenti vengono elencati tra parentesi e separati da virgole.
La definizione del metodo specifica i nomi e i tipi di tutti i parametri obbligatori. Quando il chiamante chiama il metodo, specifica valori concreti, chiamati argomenti, per ogni parametro. 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. Nell'esempio seguente il metodo Square
include un singolo parametro di tipo int
denominato 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.
public static class SquareExample
{
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. Per questa ragione, i metodi della classe Motorcycle
possono essere chiamati come nell'esempio seguente. La chiamata al metodo Drive
, ad esempio, include due argomenti che corrispondono ai due parametri nella sintassi del metodo. Il primo diventa il valore del parametro miles
. Il secondo diventa il valore del parametro speed
.
class TestMotorcycle : Motorcycle
{
public override double GetTopSpeed() => 108.4;
static void Main()
{
var 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. Quando si usano gli argomenti denominati, si specifica il nome del parametro seguito da due punti (":") e l'argomento. Gli argomenti del metodo possono essere in qualsiasi ordine, a condizione che siano presenti tutti gli argomenti necessari. L'esempio seguente usa gli argomenti denominati per richiamare il metodo TestMotorcycle.Drive
. In questo esempio gli argomenti denominati vengono passati nell'ordine inverso dall'elenco di parametri del metodo.
namespace NamedMotorCycle;
class TestMotorcycle : Motorcycle
{
public override int Drive(int miles, int speed) =>
(int)Math.Round((double)miles / speed, 0);
public override double GetTopSpeed() => 108.4;
static void Main()
{
var moto = new TestMotorcycle();
moto.StartEngine();
moto.AddGas(15);
int travelTime = moto.Drive(miles: 170, speed: 60);
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. Tuttavia, gli argomenti posizionali possono seguire solo gli argomenti denominati quando gli argomenti denominati si trovano nelle posizioni corrette. L'esempio seguente richiama il metodo TestMotorcycle.Drive
dall'esempio precedente usando un argomento posizionale e un argomento denominato.
int travelTime = moto.Drive(170, speed: 55);
Oltre ai membri definiti in modo esplicito in un tipo, un tipo eredita i membri definiti nelle relative classi base. 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(). 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. Il metodo Equals
, tuttavia, non viene definito nella classe Person
; viene ereditato da Object.
public class Person
{
public string FirstName = default!;
}
public static class ClassTypeExample
{
public static void Main()
{
Person p1 = new() { FirstName = "John" };
Person p2 = new() { 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. La firma del metodo deve essere la stessa del metodo sottoposto a override. L'esempio seguente è simile a quello precedente, ad eccezione del fatto che viene eseguito l'override del metodo Equals(Object). Viene anche eseguito l'override del metodo GetHashCode() poiché i due metodi devono fornire risultati coerenti.
namespace methods;
public class Person
{
public string FirstName = default!;
public override bool Equals(object? obj) =>
obj is Person p2 &&
FirstName.Equals(p2.FirstName);
public override int GetHashCode() => FirstName.GetHashCode();
}
public static class Example
{
public static void Main()
{
Person p1 = new() { FirstName = "John" };
Person p2 = new() { FirstName = "John" };
Console.WriteLine("p1 = p2: {0}", p1.Equals(p2));
}
}
// The example displays the following output:
// p1 = p2: True
I tipi in C# sono tipi di valore o tipi di riferimento. Per un elenco dei tipi predefiniti, consultare Tipi. Per impostazione predefinita, i tipi di valore e i tipi di riferimento vengono passati per valore a un metodo.
Quando un tipo valore viene passato a un metodo per valore, viene passata al metodo una copia dell'oggetto anziché l'oggetto stesso. Di conseguenza, le modifiche all'oggetto nel metodo chiamato non hanno effetto sull'oggetto originale quando il controllo torna al chiamante.
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. 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. Quando il metodo viene restituito, tuttavia, il valore della variabile rimane invariato.
public static class ByValueExample
{
public static void Main()
{
var 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, ovvero il metodo riceve un argomento che indica la posizione dell'oggetto, ma non l'oggetto stesso. Se si modifica un membro dell'oggetto usando questo riferimento, la modifica si riflette nell'oggetto quando il controllo torna al metodo chiamante. Tuttavia, la sostituzione dell'oggetto passato al metodo non ha effetto sull'oggetto originale quando il controllo torna al chiamante.
L'esempio seguente definisce una classe (che è un tipo riferimento) denominata SampleRefType
. Crea un'istanza di un oggetto SampleRefType
, assegna 44 al campo value
e passa l'oggetto al metodo ModifyObject
. L'esempio è sostanzialmente uguale al precedente in quanto passa un argomento per valore a un metodo. ma, essendo usato un tipo riferimento, il risultato è diverso. 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.
public class SampleRefType
{
public int value;
}
public static class ByRefTypeExample
{
public static void Main()
{
var rt = new SampleRefType { value = 44 };
ModifyObject(rt);
Console.WriteLine(rt.value);
}
static void ModifyObject(SampleRefType obj) => obj.value = 33;
}
È 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. Per passare un parametro per riferimento, usare la parola chiave ref
o out
. È anche possibile passare un valore per riferimento per evitare la copia, ma comunque impedire modifiche usando la parola chiave in
.
L'esempio seguente è identico a quello precedente, ad eccezione del fatto che il valore viene passato per riferimento al metodo ModifyValue
. Quando il valore del parametro è modificato nel metodo ModifyValue
, la modifica del valore si riflette quando il controllo torna al chiamante.
public static class ByRefExample
{
public static void Main()
{
var value = 20;
Console.WriteLine("In Main, value = {0}", value);
ModifyValue(ref value);
Console.WriteLine("Back in Main, value = {0}", value);
}
private 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. Si passano due variabili a un metodo per riferimento e il metodo scambia il loro contenuto. L'esempio seguente scambia i valori integer.
public static class RefSwapExample
{
static void Main()
{
int i = 2, j = 3;
Console.WriteLine("i = {0} j = {1}", i, j);
Swap(ref i, ref j);
Console.WriteLine("i = {0} j = {1}", i, j);
}
static void Swap(ref int x, ref int y) =>
(y, x) = (x, y);
}
// 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.
In alcuni casi, il requisito che richiede di specificare il numero esatto di argomenti per il metodo è limitativo. Usando la parola chiave params
per indicare che un parametro è una raccolta di parametri, si consente la chiamata al metodo con un numero variabile di argomenti. Il parametro contrassegnato con la parola chiave params
deve essere di tipo collezione e deve essere l'ultimo parametro dell'elenco di parametri del metodo.
Un chiamante potrà quindi richiamare il metodo in uno dei quattro modi segeunti per il parametro params
:
null
.L'esempio seguente definisce un metodo denominato GetVowels
che restituisce tutte le vocali da una collezione di parametri. Il metodo Main
illustra tutti e quattro i metodi di chiamata al metodo. Non è necessario che i chiamanti specifichino un argomento per i parametri che includono il modificatore params
. In tal caso, il parametro è una collezione vuota.
static class ParamsExample
{
static void Main()
{
string fromArray = GetVowels(["apple", "banana", "pear"]);
Console.WriteLine($"Vowels from collection expression: '{fromArray}'");
string fromMultipleArguments = GetVowels("apple", "banana", "pear");
Console.WriteLine($"Vowels from multiple arguments: '{fromMultipleArguments}'");
string fromNull = GetVowels(null);
Console.WriteLine($"Vowels from null: '{fromNull}'");
string fromNoValue = GetVowels();
Console.WriteLine($"Vowels from no value: '{fromNoValue}'");
}
static string GetVowels(params IEnumerable<string>? input)
{
if (input == null || !input.Any())
{
return string.Empty;
}
char[] vowels = ['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 null: ''
// Vowels from no value: ''
Prima di C# 13, il modificatore params
può essere usato solo con una matrice unidimensionale.
La definizione di un metodo può specificare che i parametri sono obbligatori o facoltativi. I parametri sono obbligatori per impostazione predefinita. I parametri facoltativi vengono specificati includendo il valore predefinito del parametro nella definizione del metodo. Quando il metodo viene chiamato, se non sono specificati argomenti per un parametro facoltativo, viene usato il valore predefinito.
Il valore predefinito del parametro deve essere assegnato da uno dei tipi di espressioni seguenti:
Una costante, ad esempio una stringa letterale o un numero.
Espressione del form default(SomeType)
, dove SomeType
può essere un tipo valore o un tipo riferimento. Se si tratta di un tipo riferimento, è effettivamente uguale a quello di specificare null
. È possibile usare il valore letterale default
, perché il compilatore può dedurre il tipo dalla dichiarazione del parametro.
Un'espressione del form new ValType()
, dove ValType
è un tipo di valore. Questa espressione richiama il costruttore implicito senza parametri del tipo di valore, che non è un membro effettivo del tipo.
Nota
In C# 10 e versioni successive, quando un'espressione del modulo new ValType()
richiama il costruttore senza parametri definito in modo esplicito di un tipo valore, il compilatore genera un errore come valore del parametro predefinito deve essere una costante in fase di compilazione. Usare l'espressione default(ValType)
o il valore letterale default
per fornire il valore del parametro predefinito. Per ulteriori informazioni sui costruttori senza parametri, consultare la sezione Inizializzazione struct e valori predefiniti dell'articolo Tipi di struttura.
Se un metodo include parametri obbligatori e facoltativi, i parametri facoltativi sono definiti alla fine dell'elenco di parametri, dopo tutti i parametri obbligatori.
L'esempio seguente definisce un metodo, ExampleMethod
, con un parametro obbligatorio e due facoltativi.
public class Options
{
public void ExampleMethod(int required, int optionalInt = default,
string? description = default)
{
var msg = $"{description ?? "N/A"}: {required} + {optionalInt} = {required + optionalInt}";
Console.WriteLine(msg);
}
}
Il chiamante deve fornire un argomento per tutti i parametri facoltativi fino all'ultimo parametro facoltativo per il quale viene fornito un argomento. Nel metodo ExampleMethod
, ad esempio, se il chiamante specifica un argomento per il parametro description
, deve specificarne uno anche per il parametro optionalInt
. 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".
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.
L'esempio seguente esegue una chiamata al metodo ExampleMethod
tre volte. Le prime due chiamate al metodo usano argomenti posizionali. La prima omette entrambi gli argomenti facoltativi, mentre la seconda omette l'ultimo argomento. 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
.
public static class OptionsExample
{
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:
// N/A: 10 + 0 = 10
// N/A: 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 quale overload richiamare per una chiamata al metodo, come indicato di seguito:
I metodi possono restituire un valore al chiamante. 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
. Un'istruzione con la parola chiave return
seguita da una variabile, una costante o un'espressione corrispondente al tipo restituito restituisce tale valore al chiamante del metodo. Per usare la parola chiave return
per restituire un valore, sono obbligatori metodi con un tipo restituito non void. La parola chiave return
interrompe anche l'esecuzione del metodo.
Se il tipo restituito è void
, un'istruzione return
senza un valore è tuttavia utile per interrompere l'esecuzione del metodo. Senza la parola chiave return
, l'esecuzione del metodo viene interrotta quando verrà raggiunta la fine del blocco di codice.
Ad esempio, questi due metodi usano la parola chiave return
per restituire numeri interi:
class SimpleMath
{
public int AddTwoNumbers(int number1, int number2) =>
number1 + number2;
public int SquareANumber(int number) =>
number * number;
}
Gli esempi precedenti sono membri con corpo di espressione. I membri con corpo di espressione restituiscono il valore fornito dall'espressione.
È inoltre possibile scegliere di definire i metodi con un corpo dell'istruzione e un'istruzione return
:
class SimpleMathExtnsion
{
public int DivideTwoNumbers(int number1, int number2)
{
return number1 / number2;
}
}
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. È inoltre possibile assegnare il valore restituito a una variabile. I tre esempi seguenti di codice ottengono lo stesso risultato:
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);
result = obj2.DivideTwoNumbers(6,2);
// The result is 3.
Console.WriteLine(result);
In alcuni casi, si vuole che il metodo restituisca più di un singolo valore. Usare tipi di tupla e valori letterali di tupla per restituire più valori. Il tipo di tupla definisce i tipi di dati degli elementi della tupla. I letterali di tupla specificano i valori effettivi della tupla restituita. Nell'esempio seguente (string, string, string, int)
definisce il tipo di tupla restituito dal metodo GetPersonalInfo
. L'espressione (per.FirstName, per.MiddleName, per.LastName, per.Age)
è il letterale della tupla; il metodo restituisce il nome, il secondo nome, il cognome e l’età di un oggetto PersonInfo
.
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 usando il codice seguente:
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. L'esempio seguente mostra una versione alternativa del metodo GetPersonalInfo
che usa elementi denominati:
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 GetPersonalInfo
può quindi essere modificata come segue:
var person = GetPersonalInfo("111111111");
Console.WriteLine($"{person.FName} {person.LName}: age = {person.Age}");
Se un metodo accetta una matrice come parametro e modifica il valore di singoli elementi, non è necessario che il metodo restituisca la matrice. C# passa tutti i tipi riferimento per valore e il valore di un riferimento a una matrice è il puntatore alla matrice. 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.
public static class ArrayValueExample
{
static void Main()
{
int[] values = [2, 4, 6, 8];
DoubleValues(values);
foreach (var value in values)
{
Console.Write("{0} ", value);
}
}
public static void DoubleValues(int[] arr)
{
for (var ctr = 0; ctr <= arr.GetUpperBound(0); ctr++)
{
arr[ctr] *= 2;
}
}
}
// The example displays the following output:
// 4 8 12 16
In genere, è possibile aggiungere un metodo a un tipo esistente in due modi:
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. È necessario anche che il metodo di estensione non si trovi nello stesso assembly del tipo che estende. Un metodo di estensione viene chiamato come se fosse un membro definito di un tipo.
Per altre informazioni, vedere Metodi di estensione.
Tramite la funzionalità async, è possibile richiamare i metodi asincroni senza usare callback espliciti o suddividere manualmente il codice in più metodi o espressioni lambda.
Se si contrassegna un metodo con il modificatore async , è possibile usare l'operatore await nel metodo. 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. Una volta completata l'attività, l'esecuzione del metodo può riprendere.
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.
Un metodo asincrono ha in genere un tipo restituito di Task<TResult>, Task, IAsyncEnumerable<T> o void
. Il tipo restituito void
viene usato principalmente per definire i gestori eventi in cui è necessario un tipo restituito void
. 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. Un metodo asincrono può avere qualsiasi tipo restituito simile a un'attività.
Nell'esempio seguente DelayAsync
è un metodo asincrono con un'istruzione return che restituisce un valore Integer. Poiché si tratta di un metodo asincrono, la dichiarazione del metodo deve avere un tipo restituito di 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.
class Program
{
static Task Main() => DoSomethingAsync();
static async Task DoSomethingAsync()
{
Task<int> delayTask = DelayAsync();
int result = await delayTask;
// The previous two statements may be combined into
// the following statement.
//int result = await DelayAsync();
Console.WriteLine($"Result: {result}");
}
static async Task<int> DelayAsync()
{
await Task.Delay(100);
return 5;
}
}
// Example output:
// Result: 5
Un metodo asincrono non può dichiarare parametri in, ref o out, ma può chiamare metodi che hanno tali parametri.
Per ulteriori informazioni sulla funzionalità dei metodi asincroni, Consultare Programmazione asincrona con async e await e Tipi async restituiti.
È comune disporre di definizioni di metodo che restituiscono subito il risultato di un'espressione o che includono una singola istruzione come corpo del metodo. Esiste una sintassi breve per definire tali metodi usando =>
:
public Point Move(int dx, int dy) => new Point(x + dx, y + dy);
public void Print() => Console.WriteLine(First + " " + Last);
// Works with operators, properties, and indexers too.
public static Complex operator +(Complex a, Complex b) => a.Add(b);
public string Name => First + " " + Last;
public Customer this[long id] => store.LookupCustomer(id);
Se il metodo restituisce void
o è un metodo asincrono, il corpo del metodo deve essere un'espressione di istruzione (come per le espressioni lambda). Per le proprietà e gli indicizzatori, devono essere di sola lettura e non è necessario usare la parola chiave della funzione di accesso get
.
Un iteratore esegue un'iterazione personalizzata su una raccolta, ad esempio un elenco o una matrice. Un iteratore usa l'istruzione yield return per restituire un elemento per volta. Quando viene raggiunta un'istruzione yield return
, viene memorizzata la posizione corrente in modo che il chiamante possa richiedere l'elemento successivo della sequenza.
Il tipo restituito di un iteratore può essere IEnumerable, IEnumerable<T>, IAsyncEnumerable<T>, IEnumerator o IEnumerator<T>.
Per altre informazioni, vedere Iteratori.
Feedback su .NET
.NET è un progetto di open source. Selezionare un collegamento per fornire feedback:
Formazione
Modulo
Creare metodi C# che restituiscono valori - Training
Questo modulo descrive la parola chiave return e la restituzione di valori dai metodi.