Expression-bodied members (C# programming guide)
Expression body definitions let you provide a member's implementation in a concise, readable form. You can use an expression body definition whenever the logic for any supported member, such as a method or property, consists of a single expression. An expression body definition has the following general syntax:
member => expression;
where expression is a valid expression.
Expression body definitions can be used with the following type members:
Methods
An expression-bodied method consists of a single expression that returns a value whose type matches the method's return type, or, for methods that return void
, that performs some operation. For example, types that override the ToString method typically include a single expression that returns the string representation of the current object.
The following example defines a Person
class that overrides the ToString method with an expression body definition. It also defines a DisplayName
method that displays a name to the console. The return
keyword is not used in the ToString
expression body definition.
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();
}
}
For more information, see Methods (C# Programming Guide).
Read-only properties
You can use expression body definition to implement a read-only property. To do that, use the following syntax:
PropertyType PropertyName => expression;
The following example defines a Location
class whose read-only Name
property is implemented as an expression body definition that returns the value of the private locationName
field:
public class Location
{
private string locationName;
public Location(string name)
{
locationName = name;
}
public string Name => locationName;
}
For more information about properties, see Properties (C# Programming Guide).
Properties
You can use expression body definitions to implement property get
and set
accessors. The following example demonstrates how to do that:
public class Location
{
private string locationName;
public Location(string name) => Name = name;
public string Name
{
get => locationName;
set => locationName = value;
}
}
For more information about properties, see Properties (C# Programming Guide).
Events
Similarly, event add
and remove
accessors can be expression-bodied:
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) });
}
}
For more information about events, see Events (C# Programming Guide).
Constructors
An expression body definition for a constructor typically consists of a single assignment expression or a method call that handles the constructor's arguments or initializes instance state.
The following example defines a Location
class whose constructor has a single string parameter named name. The expression body definition assigns the argument to the Name
property.
public class Location
{
private string locationName;
public Location(string name) => Name = name;
public string Name
{
get => locationName;
set => locationName = value;
}
}
For more information, see Constructors (C# Programming Guide).
Finalizers
An expression body definition for a finalizer typically contains cleanup statements, such as statements that release unmanaged resources.
The following example defines a finalizer that uses an expression body definition to indicate that the finalizer has been called.
public class Destroyer
{
public override string ToString() => GetType().Name;
~Destroyer() => Console.WriteLine($"The {ToString()} finalizer is executing.");
}
For more information, see Finalizers (C# Programming Guide).
Indexers
Like with properties, indexer get
and set
accessors consist of expression body definitions if the get
accessor consists of a single expression that returns a value or the set
accessor performs a simple assignment.
The following example defines a class named Sports
that includes an internal String array that contains the names of some sports. Both the indexer get
and set
accessors are implemented as expression body definitions.
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;
}
}
For more information, see Indexers (C# Programming Guide).