Freigeben über


Ausdruckskörpermember (C#-Programmierhandbuch)

Mit Ausdruckskörperdefinitionen können Sie die Implementierung eines Members in einer präzisen und lesbaren Form darstellen. Sie können eine Ausdruckstextdefinition verwenden, wann immer die Logik für einen unterstützten Member, z.B. eine Methode oder Eigenschaft, aus einem einzelnen Ausdruck besteht. Eine Ausdruckstextdefinition hat die folgende allgemeine Syntax:

member => expression;

wobei expression ein gültiger Ausdruck ist.

Ausdruckstextdefinitionen können mit den folgenden Typmembern verwendet werden:

Methoden

Eine Ausdruckskörpermethode besteht aus einem einzelnen Ausdruck, der einen Wert zurückgibt, dessen Typ mit dem Rückgabetyp der Methode übereinstimmt bzw. für Methoden, die void zurückgeben, das einige Vorgänge ausführt. Beispielsweise enthalten Typen, die die ToString-Methode außer Kraft setzen normalerweise einen einzelnen Ausdruck, der die Zeichenfolgendarstellung des aktuellen Objekts zurückgibt.

Das folgende Beispiel definiert eine Person-Klasse, die die ToString-Methode mit einer Ausdruckstextmethode außer Kraft setzt. Es wird auch eine DisplayName-Methode definiert, die einen Namen für die Konsole anzeigt. Darüber hinaus enthält es mehrere Methoden, die Parameter annehmen, um zu demonstrieren, wie Member mit Expression-Bodys mit Methodenparametern arbeiten. Das return Schlüsselwort wird in keiner der Ausdruckstextdefinitionen verwendet.

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());
   
   // Expression-bodied methods with parameters
   public string GetFullName(string title) => $"{title} {fname} {lname}";
   public int CalculateAge(int birthYear) => DateTime.Now.Year - birthYear;
   public bool IsOlderThan(int age) => CalculateAge(1990) > age;
   public string FormatName(string format) => format.Replace("{first}", fname).Replace("{last}", lname);
}

class Example
{
   public static void Main()
   {
      Person p = new Person("Mandy", "Dejesus");
      Console.WriteLine(p);
      p.DisplayName();
      
      // Examples with parameters
      Console.WriteLine(p.GetFullName("Dr."));
      Console.WriteLine($"Age: {p.CalculateAge(1990)}");
      Console.WriteLine($"Is older than 25: {p.IsOlderThan(25)}");
      Console.WriteLine(p.FormatName("Last: {last}, First: {first}"));
   }
}

Weitere Informationen finden Sie unter Methoden (C#-Programmierhandbuch).

Schreibgeschützte Eigenschaften

Sie können eine Ausdruckstextdefinition verwenden, um eine schreibgeschützte Eigenschaft zu implementieren. Verwenden Sie hierzu die folgende Syntax:

PropertyType PropertyName => expression;

Im folgenden Beispiel wird eine Location-Klasse definiert, deren schreibgeschützte Eigenschaft Name als Ausdruckskörperdefinition implementiert wird, die den Wert des privaten locationName-Felds zurückgibt:

public class Location
{
   private string locationName;

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

   public string Name => locationName;
}

Weitere Informationen zu Eigenschaften finden Sie unter Eigenschaften (C#-Programmierhandbuch).

Eigenschaften

Sie können Ausdruckstextdefinitionen zum Implementieren von get-Eigenschaften und set-Accessoren verwenden. Im folgenden Beispiel wird die dafür erforderliche Vorgehensweise veranschaulicht:

public class Location
{
   private string locationName;

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

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

// Example with multiple parameters
public class Point
{
   public double X { get; }
   public double Y { get; }
   
   // Constructor with multiple parameters
   public Point(double x, double y) => (X, Y) = (x, y);
   
   // Constructor with single parameter (creates point at origin on axis)
   public Point(double coordinate) => (X, Y) = (coordinate, 0);
}

Weitere Informationen zu Eigenschaften finden Sie unter Eigenschaften (C#-Programmierhandbuch).

Ereignisse

In ähnlicher Weise können auch die Ereignisse add und remove Accessors mit einem Ausdruck versehen werden:

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

Weitere Informationen über Ereignisse finden Sie unter Ereignisse (C# Programmieranleitung).

Konstruktoren

Eine Ausdruckstextdefinition für einen Konstruktor enthält in der Regel einen einzelnen Zuweisungsausdruck oder einen Methodenaufruf, der die Argumente des Konstruktors behandelt oder den Instanzzustand initialisiert.

Im folgenden Beispiel wird eine Location-Klasse definiert, deren Klassenkonstruktor einen einzelnen Zeichenfolgenparameter namens name enthält. Die Ausdruckstextdefinition weist das Argument für die Eigenschaft Name zu. Das Beispiel zeigt auch eine Point Klasse mit Konstruktoren, die mehrere Parameter verwenden, und zeigt, wie Ausdruckskörperkonstruktoren mit verschiedenen Parameterkombinationen funktionieren.

public class Location
{
   private string locationName;

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

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

// Example with multiple parameters
public class Point
{
   public double X { get; }
   public double Y { get; }
   
   // Constructor with multiple parameters
   public Point(double x, double y) => (X, Y) = (x, y);
   
   // Constructor with single parameter (creates point at origin on axis)
   public Point(double coordinate) => (X, Y) = (coordinate, 0);
}

Weitere Informationen finden Sie unter Konstruktoren (C#-Programmierhandbuch).

Finalizer

Eine Ausdruckstextdefinition für einen Finalizer enthält normalerweise Bereinigungsanweisungen, z.B. Anweisungen, die nicht verwaltete Ressourcen veröffentlichen.

Im folgenden Beispiel wird ein Finalizer definiert, der eine Ausdruckstextdefinition verwendet, um anzugeben, dass der Finalizer aufgerufen wurde.

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

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

Weitere Informationen finden Sie unter Finalizer (C#-Programmierhandbuch).

Indexer

Genauso wie Eigenschaften bestehen die get- und set-Accessoren des Indexers aus Ausdruckstextdefinitionen, wenn der get-Accessor aus einem einzelnen Ausdruck besteht, der einen Wert zurückgibt, oder der set-Accessor führt eine einfache Zuweisung aus.

Im folgenden Beispiel wird eine Klasse namens Sports definiert, die ein internes String-Array enthält, das aus den Namen einiger Sportarten besteht. Die get- und set-Accessoren des Indexers werden als Ausdruckstextdefinitionen implementiert.

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

Weitere Informationen finden Sie unter Indexer (C#-Programmierhandbuch).

Weitere Informationen