Condividi tramite


Membri con corpo di espressione (Guida per programmatori C#)

Le definizioni di corpo dell'espressione consentono di fornire l'implementazione di un membro in modo conciso e leggibile. È possibile usare una definizione di corpo di espressione ogni volta che la logica per un membro supportato, ad esempio un metodo o proprietà, è costituita da un'unica espressione. Una definizione di corpo di espressione presenta la seguente sintassi generale:

member => expression;

dove expression è un'espressione valida.

Le definizioni di corpo dell'espressione possono essere usate con i membri dei tipi seguenti:

Metodi

Un metodo con corpo di espressione è costituito da una singola espressione che restituisce un valore il cui tipo corrisponde al tipo restituito del metodo oppure, per i metodi che restituiscono void, che esegue una determinata operazione. Ad esempio, i tipi che eseguono l'override del metodo ToString di solito includono una singola espressione che restituisce la rappresentazione di stringa dell'oggetto corrente.

L'esempio seguente definisce una classe Person che esegue l'override del metodo ToString con una definizione di corpo di espressione. Definisce inoltre un metodo DisplayName che visualizza un nome nella console. La parola chiave return non viene usata nella definizione del corpo dell'espressione ToString.

using System;

namespace ExpressionBodiedMembers;

public class Person
{
   public Person(string firstName, string lastName)
   {
      fname = firstName;
      lname = lastName;
   }

   private string fname;
   private string lname;

   public override string ToString() => $"{fname} {lname}".Trim();
   public void DisplayName() => Console.WriteLine(ToString());
}

class Example
{
   static void Main()
   {
      Person p = new Person("Mandy", "Dejesus");
      Console.WriteLine(p);
      p.DisplayName();
   }
}

Per altre informazioni, vedere Metodi (Guida per programmatori C#).

Proprietà di sola lettura

È possibile usare una definizione di corpo dell'espressione per implementare una proprietà di sola lettura. A questo scopo, usare la sintassi seguente:

PropertyType PropertyName => expression;

L'esempio seguente definisce una classe Location la cui proprietà Name di sola lettura viene implementata come definizione del corpo dell'espressione che restituisce il valore del campo locationName privato:

public class Location
{
   private string locationName;

   public Location(string name)
   {
      locationName = name;
   }

   public string Name => locationName;
}

Per altre informazioni sulle proprietà, vedere Proprietà (Guida per programmatori C#).

Proprietà

È possibile usare le definizioni di corpo dell'espressione per implementare le funzioni di accesso get e set delle proprietà. Nell'esempio riportato di seguito viene illustrato come procedere:

public class Location
{
   private string locationName;

   public Location(string name) => Name = name;

   public string Name
   {
      get => locationName;
      set => locationName = value;
   }
}

Per altre informazioni sulle proprietà, vedere Proprietà (Guida per programmatori C#).

Eventi

Analogamente, i add di eventi e le funzioni di accesso remove possono essere con corpo di espressione:

public class ChangedEventArgs : EventArgs
{
   public required int NewValue { get; init; }
}

public class ObservableNum(int _value)
{
   public event EventHandler<ChangedEventArgs> ChangedGeneric = default!;

   public event EventHandler Changed
   {
      // Note that, while this is syntactically valid, it won't work as expected because it's creating a new delegate object with each call.
      add => ChangedGeneric += (sender, args) => value(sender, args);
      remove => ChangedGeneric -= (sender, args) => value(sender, args);
   }

   public int Value
   {
      get => _value;
      set => ChangedGeneric?.Invoke(this, new() { NewValue = (_value = value) });
   }
}

Per altre informazioni sugli eventi, vedere Eventi (Guida per programmatori C#).

Costruttori

Una definizione di corpo di espressione per un costruttore in genere è costituita da una singola espressione di assegnazione o da una chiamata al metodo che gestisce gli argomenti del costruttore o inizializza lo stato dell'istanza.

L'esempio seguente definisce una classe Location il cui costruttore ha un solo parametro di stringa denominato name. La definizione del corpo dell'espressione assegna l'argomento alla proprietà Name.

public class Location
{
   private string locationName;

   public Location(string name) => Name = name;

   public string Name
   {
      get => locationName;
      set => locationName = value;
   }
}

Per altre informazioni, vedere Costruttori (Guida per programmatori C#).

Finalizzatori

Una definizione di corpo di espressione per un finalizzatore in genere contiene istruzioni di pulitura, ad esempio le istruzioni che rilasciano risorse non gestite.

L'esempio seguente definisce un finalizzatore che usa una definizione di corpo di espressione per indicare che è stato chiamato il finalizzatore.

public class Destroyer
{
   public override string ToString() => GetType().Name;

   ~Destroyer() => Console.WriteLine($"The {ToString()} finalizer is executing.");
}

Per altre informazioni, vedere Finalizzatori (Guida per programmatori C#).

Indicizzatori

Come per le proprietà, le funzioni di accesso get e set degli indicizzatori sono costituite da definizioni di corpo dell'espressione se get è costituita da una singola espressione che restituisce un valore o set esegue un'assegnazione semplice.

L'esempio seguente definisce una classe denominata Sports che include una matrice String interna contenente i nomi di alcuni sport. Le funzioni di accesso get e set degli indicizzatori sono entrambe implementate come definizioni di corpo dell'espressione.

using System;
using System.Collections.Generic;

namespace SportsExample;

public class Sports
{
   private string[] types = [ "Baseball", "Basketball", "Football",
                              "Hockey", "Soccer", "Tennis",
                              "Volleyball" ];

   public string this[int i]
   {
      get => types[i];
      set => types[i] = value;
   }
}

Per altre informazioni, vedere Indicizzatori (Guida per programmatori C#).

Vedi anche