Membros com corpo de expressão (guia de programação em C#)

As definições do corpo da expressão permitem fornecer a implementação de um membro de forma concisa e legível. Você pode usar uma definição de corpo de expressão sempre que a lógica para qualquer membro suportado, como um método ou propriedade, consistir em uma única expressão. Uma definição de corpo de expressão tem a seguinte sintaxe geral:

member => expression;

onde expressão é uma expressão válida.

As definições de corpo de expressão podem ser usadas com os seguintes membros de tipo:

Métodos

Um método com corpo de expressão consiste em uma única expressão que retorna um valor cujo tipo corresponde ao tipo de retorno do método ou, para métodos que retornam void, que executa alguma operação. Por exemplo, os tipos que substituem o ToString método normalmente incluem uma única expressão que retorna a representação de cadeia de caracteres do objeto atual.

O exemplo a seguir define uma Person classe que substitui o ToString método por uma definição de corpo de expressão. Ele também define um DisplayName método que exibe um nome para o console. A return palavra-chave não é usada na definição do corpo da ToString expressão.

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

Para obter mais informações, consulte Métodos (Guia de Programação em C#).

Propriedades só de leitura

Você pode usar a definição de corpo de expressão para implementar uma propriedade somente leitura. Para fazer isso, use a seguinte sintaxe:

PropertyType PropertyName => expression;

O exemplo a seguir define uma Location classe cuja propriedade somente Name leitura é implementada como uma definição de corpo de expressão que retorna o valor do campo privado locationName :

public class Location
{
   private string locationName;

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

   public string Name => locationName;
}

Para obter mais informações sobre propriedades, consulte Propriedades (Guia de Programação em C#).

Propriedades

Você pode usar definições de corpo de expressão para implementar propriedades get e set acessadores. O exemplo a seguir demonstra como fazer isso:

public class Location
{
   private string locationName;

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

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

Para obter mais informações sobre propriedades, consulte Propriedades (Guia de Programação em C#).

evento

Da mesma forma, eventos add e remove acessadores podem ser corporizados por expressão:

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

Para obter mais informações sobre eventos, consulte Eventos (Guia de Programação em C#).

Construtores

Uma definição de corpo de expressão para um construtor normalmente consiste em uma única expressão de atribuição ou uma chamada de método que manipula os argumentos do construtor ou inicializa o estado da instância.

O exemplo a seguir define uma Location classe cujo construtor tem um único parâmetro string chamado name. A definição do corpo da expressão atribui o argumento à Name propriedade.

public class Location
{
   private string locationName;

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

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

Para obter mais informações, consulte Construtores (Guia de Programação em C#).

Finalizadores

Uma definição de corpo de expressão para um finalizador normalmente contém instruções de limpeza, como instruções que liberam recursos não gerenciados.

O exemplo a seguir define um finalizador que usa uma definição de corpo de expressão para indicar que o finalizador foi chamado.

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

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

Para obter mais informações, consulte Finalizadores (Guia de Programação em C#).

Indexadores

Como acontece com as propriedades, indexador get e set acessadores consistem em definições de corpo de expressão se o get acessador consiste em uma única expressão que retorna um valor ou o set acessador executa uma atribuição simples.

O exemplo a seguir define uma classe chamada Sports que inclui uma matriz interna String que contém os nomes de alguns esportes. Tanto o indexador get quanto set os acessadores são implementados como definições de corpo de expressão.

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

Para obter mais informações, consulte Indexadores (Guia de Programação em C#).

Consulte também