Expression-Bodied Members

When a member's whole body is one expression, => replaces the braces and the return keyword, and compiles to exactly the same thing.

Syntaxmember => expression;

Many methods are one line long: work out a value, hand it back. An expression body writes that without the ceremony. Instead of braces and return, you write => and the expression. The two forms are the same method; the compiler produces the same code for both.

The two forms side by side

int Triple(int n)
{
    return n * 3;
}

int Triple(int n) => n * 3;

For a member that returns a value, the expression's result must be convertible to the return type. For a void member the body must be a statement expression: something that can stand alone as a statement, such as a method call, an assignment, or an object creation. An if statement is not an expression, so it cannot be used.

Where it is allowed

Methods, local functions, operators, read-only properties and indexers, individual get, set and init accessors, constructors, finalizers, and add and remove event accessors. A property is a member that looks like a field from outside but runs code; Stage 3 covers properties. Methods and read-only properties got expression bodies in C# 6; C# 7.0 extended them to constructors, finalizers and accessors.

What trips people up

The => token also writes lambda expressions, which are a different feature. Here it only separates a member's name from its implementation. And a long expression crammed after => is harder to read than braces, not easier.

Example

Example · csharp
// Braced form: braces, and an explicit return.
int DoubleIt(int n)
{
    return n * 2;
}

// Expression body: the same method, written with =>.
// No braces and no return keyword. The compiled result is identical.
int TripleIt(int n) => n * 3;

// void works too, as long as the body is a single statement expression.
void Shout(string text) => Console.WriteLine(text.ToUpperInvariant());

Console.WriteLine(DoubleIt(21));
Console.WriteLine(TripleIt(14));
Shout("done");

// Output:
// 42
// 42
// DONE

When to use it

  • Shorten a one-line getter or helper method without changing what it compiles to.
  • Recognise => in someone else's code and know whether it is a member body or a lambda.
  • Write a lookup method whose whole body is a single switch expression.

More examples

Braced and expression-bodied properties together

The two properties are written differently and behave identically. Computed read-only properties are where expression bodies pay off most, and you will see both spellings in real code.

Example · csharp
Box box = new Box();
box.Width = 4;
box.Height = 6;

Console.WriteLine(box.Area);
Console.WriteLine(box.Perimeter);

// Output:
// 24
// 20

struct Box
{
    public int Width;
    public int Height;

    // Read-only property, braced form.
    public int Area
    {
        get { return Width * Height; }
    }

    // Read-only property, expression body. Same thing, four lines shorter.
    public int Perimeter => 2 * (Width + Height);
}

An expression body over a switch expression

A switch expression produces a value, so it is a legal expression body. Note that the => inside the switch arms is a different use of the same token: there it separates a pattern from its result.

Example · csharp
// The body is one expression, so => fits, even though it spans six lines.
string Grade(int score) => score switch
{
    >= 90 => "A",
    >= 80 => "B",
    >= 70 => "C",
    _ => "F"
};

Console.WriteLine(Grade(95));
Console.WriteLine(Grade(72));
Console.WriteLine(Grade(40));

// Output:
// A
// C
// F

What counts as a statement expression

This is the rule people hit first: a void expression body takes a call or an assignment, not control flow. When you need a branch, either switch to the conditional operator or go back to braces.

Example · csharp
// A method call is a statement expression, so this is allowed.
void LogLine(string text) => Console.WriteLine($"- {text}");

int total = 0;

// An assignment is also a statement expression.
void Add(int amount) => total += amount;

// Not allowed: an if statement is not an expression.
// void Guard(int n) => if (n < 0) { Console.WriteLine("negative"); }

// The conditional operator is an expression, so use that instead.
string Sign(int n) => n < 0 ? "negative" : "positive";

Add(40);
Add(2);
LogLine($"total {total}");
LogLine(Sign(-3));

// Output:
// - total 42
// - negative

Discussion

  • Be the first to comment on this lesson.