Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
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.
Il Main
metodo è il punto di ingresso per ogni applicazione C# e viene chiamato da Common Language Runtime (CLR) all'avvio del programma. In un'applicazione che usa istruzioni di primo livello, il Main
metodo viene generato dal compilatore e contiene tutte le istruzioni di primo livello.
Annotazioni
Questo articolo illustra i metodi denominati. Per informazioni sulle funzioni anonime, consultare Espressioni lambda.
Firme dei metodi
I metodi vengono dichiarati in una classe, uno struct o un'interfaccia specificando il livello di accesso, public
ad esempio o private
, modificatori facoltativi come abstract
o sealed
, il valore restituito, il nome del metodo e qualsiasi parametro del metodo. Queste parti insieme sono la firma del metodo .
Importante
Il tipo di ritorno di un metodo non fa parte della firma del metodo ai fini del sovraccarico dei metodi. Fa tuttavia parte della firma del metodo quando si determina la compatibilità tra un delegato e il metodo a cui fa riferimento.
I parametri del metodo vengono racchiusi tra parentesi e separati da virgole. Le parentesi vuote indicano che il metodo non richiede parametri. Questa classe contiene quattro metodi:
abstract class Motorcycle
{
// Anyone can call this.
public void StartEngine() {/* Method statements here */ }
// Only derived classes can call this.
protected void AddGas(int gallons) { /* Method statements here */ }
// Derived classes can override the base class implementation.
public virtual int Drive(int miles, int speed) { /* Method statements here */ return 1; }
// Derived classes must implement this.
public abstract double GetTopSpeed();
}
Accesso al metodo
La chiamata a un metodo su un oggetto è simile all'accesso a un campo. Dopo il nome dell'oggetto, aggiungere un punto, il nome del metodo e le parentesi. Gli argomenti sono elencati tra parentesi e sono separati da virgole. I metodi della Motorcycle
classe possono quindi essere chiamati come nell'esempio seguente:
class TestMotorcycle : Motorcycle
{
public override double GetTopSpeed()
{
return 108.4;
}
static void Main()
{
TestMotorcycle moto = new TestMotorcycle();
moto.StartEngine();
moto.AddGas(15);
moto.Drive(5, 20);
double speed = moto.GetTopSpeed();
Console.WriteLine($"My top speed is {speed}");
}
}
Parametri del metodo e argomenti
La definizione del metodo specifica i nomi e i tipi di tutti i parametri obbligatori. Quando il codice invocante chiama il metodo, vengono forniti valori concreti denominati argomenti per ciascun parametro. Gli argomenti devono essere compatibili con il tipo di parametro, ma il nome dell'argomento (se presente) usato nel codice chiamante non deve essere uguale al parametro denominato definito nel metodo . Per esempio:
public void Caller()
{
int numA = 4;
// Call with an int variable.
int productA = Square(numA);
int numB = 32;
// Call with another int variable.
int productB = Square(numB);
// Call with an integer literal.
int productC = Square(12);
// Call with an expression that evaluates to int.
productC = Square(productA * 3);
}
int Square(int i)
{
// Store input argument in a local variable.
int input = i;
return input * input;
}
Passaggio per riferimento e passaggio per valore
Per impostazione predefinita, quando un'istanza di un tipo valore viene passata a un metodo, la copia viene passata anziché l'istanza stessa. Di conseguenza, le modifiche apportate all'argomento non hanno alcun effetto sull'istanza originale nel metodo chiamante. Per passare un'istanza di tipo valore per riferimento, usare la ref
parola chiave . Per altre informazioni, vedere Passaggio di parametri Value-Type.
Quando un oggetto di un tipo riferimento viene passato a un metodo, viene passato un riferimento all'oggetto . Ovvero, il metodo riceve non l'oggetto stesso, ma un argomento che indica la posizione dell'oggetto. Se si modifica un membro dell'oggetto utilizzando questo riferimento, la modifica si riflette nell'argomento nel metodo chiamante, anche se si passa l'oggetto per valore.
Per creare un tipo riferimento, usare la class
parola chiave , come illustrato nell'esempio seguente:
public class SampleRefType
{
public int value;
}
Ora, se si passa un oggetto basato su questo tipo a un metodo, viene passato un riferimento all'oggetto . Nell'esempio seguente viene passato un oggetto di tipo SampleRefType
al metodo ModifyObject
:
public static void TestRefType()
{
SampleRefType rt = new SampleRefType();
rt.value = 44;
ModifyObject(rt);
Console.WriteLine(rt.value);
}
static void ModifyObject(SampleRefType obj)
{
obj.value = 33;
}
L'esempio esegue essenzialmente la stessa operazione dell'esempio precedente in quanto passa un argomento per valore a un metodo. Tuttavia, poiché viene usato un tipo riferimento, il risultato è diverso. La modifica apportata al campo value
del parametro, obj
, cambia anche il campo value
dell'argomento, rt
, nel metodo TestRefType
. Il TestRefType
metodo visualizza 33 come output.
Per ulteriori informazioni su come passare i tipi di riferimento per riferimento e per valore, vedere Passaggio di Reference-Type parametri e Tipi di riferimento.
Valori restituiti
I metodi possono restituire un valore al chiamante. Se il tipo restituito (il tipo elencato prima del nome del metodo) non è void
, il metodo può restituire il valore usando l'istruzione return
. Un'istruzione con la return
parola chiave seguita da un valore che corrisponde al tipo restituito restituirà tale valore al chiamante del metodo.
Il valore può essere restituito al chiamante per valore o per riferimento. I valori vengono restituiti al chiamante per riferimento se la ref
parola chiave viene usata nella firma del metodo e segue ogni return
parola chiave. Ad esempio, la firma del metodo e l'istruzione return seguenti indicano che il metodo restituisce una variabile denominata estDistance
per riferimento al chiamante.
public ref double GetEstimatedDistance()
{
return ref estDistance;
}
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 return
parola chiave , il metodo smetterà di eseguire quando raggiunge la fine del blocco di codice. I metodi con un tipo di ritorno non void devono usare la parola chiave return
per restituire un valore. Ad esempio, questi due metodi usano la parola chiave return
per restituire numeri interi:
class SimpleMath
{
public int AddTwoNumbers(int number1, int number2)
{
return number1 + number2;
}
public int SquareANumber(int number)
{
return number * number;
}
}
Per utilizzare un valore restituito da un metodo, il metodo chiamante può usare la chiamata al metodo stesso in qualsiasi punto in cui un valore dello stesso tipo sia sufficiente. È anche possibile assegnare il valore restituito a una variabile. Ad esempio, i due esempi di codice seguenti hanno lo stesso obiettivo:
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. Può contribuire alla leggibilità del codice oppure potrebbe essere necessario se è necessario archiviare il valore originale dell'argomento per l'intero ambito del metodo.
Per usare un valore restituito dal riferimento da un metodo, è necessario dichiarare una variabile locale ref se si intende modificarne il valore. Ad esempio, se il Planet.GetEstimatedDistance
metodo restituisce un Double valore per riferimento, è possibile definirlo come variabile locale ref con codice simile al seguente:
ref double distance = ref Planet.GetEstimatedDistance();
La restituzione di una matrice multidimensionale da un metodo , M
che modifica il contenuto della matrice non è necessaria se la funzione chiamante ha passato la matrice a M
. È possibile restituire la matrice risultante da M
per uno stile corretto o un flusso funzionale di valori, ma non è necessario perché C# passa tutti i tipi di riferimento per valore e il valore di un riferimento di matrice è il puntatore alla matrice. Nel metodo M
tutte le modifiche apportate al contenuto della matrice sono osservabili da qualsiasi codice con un riferimento alla matrice, come illustrato nell'esempio seguente:
static void Main(string[] args)
{
int[,] matrix = new int[2, 2];
FillMatrix(matrix);
// matrix is now full of -1
}
public static void FillMatrix(int[,] matrix)
{
for (int i = 0; i < matrix.GetLength(0); i++)
{
for (int j = 0; j < matrix.GetLength(1); j++)
{
matrix[i, j] = -1;
}
}
}
Metodi asincroni
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 e l'esecuzione del metodo viene sospesa fino al completamento del task atteso. Una volta completata l'attività, l'esecuzione del metodo può riprendere.
Annotazioni
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 di ritorno simile a un'attività.
Nell'esempio seguente è DelayAsync
un metodo asincrono che ha un tipo restituito di Task<TResult>.
DelayAsync
ha un'istruzione return
che restituisce un numero intero. Pertanto, la dichiarazione del metodo di DelayAsync
deve avere un tipo restituito di Task<int>
. Poiché il tipo restituito è Task<int>
, la valutazione dell'espressione await
in DoSomethingAsync
produce un numero intero come illustrato nell'istruzione seguente: int result = await delayTask
.
Il Main
metodo è un esempio di metodo asincrono con un tipo restituito di Task. Passa al DoSomethingAsync
metodo e, poiché è espresso con una singola riga, può omettere le async
parole chiave e await
. Poiché DoSomethingAsync
è un metodo asincrono, il task per la chiamata a DoSomethingAsync
deve essere atteso, come illustrato nell'istruzione seguente: await DoSomethingAsync();
.
class Program
{
static Task Main() => DoSomethingAsync();
static async Task DoSomethingAsync()
{
Task<int> delayTask = DelayAsync();
int result = await delayTask;
// The previous two statements may be combined into
// the following statement.
//int result = await DelayAsync();
Console.WriteLine($"Result: {result}");
}
static async Task<int> DelayAsync()
{
await Task.Delay(100);
return 5;
}
}
// Example output:
// Result: 5
Un metodo asincrono non può dichiarare parametri ref o out , ma può chiamare metodi con tali parametri.
Per ulteriori informazioni sui metodi asincroni, vedere Programmazione asincrona con async e await e Tipi restituiti asincroni.
Definizioni di corpo di espressione
È comune avere definizioni di metodo che restituiscono immediatamente il risultato di un'espressione o che hanno una singola istruzione nel corpo del metodo. Esiste un collegamento alla sintassi 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 (uguale a quella delle espressioni lambda). Per le proprietà e gli indicizzatori, devono essere di sola lettura e non si usa la parola chiave della get
funzione di accesso.
Iteratori
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 nel codice. L'esecuzione viene riavviata da tale posizione quando l'iteratore viene chiamato la volta successiva.
Si chiama un iteratore dal codice client usando un'istruzione foreach .
Il tipo restituito di un iteratore può essere IEnumerable, IEnumerable<T>, IAsyncEnumerable<T>, IEnumerator o IEnumerator<T>.
Per altre informazioni, vedere Iteratori.
Specifiche del linguaggio C#
Per ulteriori informazioni, consulta le Specifiche del linguaggio C# . La specifica del linguaggio costituisce il riferimento ufficiale principale per la sintassi e l'uso di C#.