C# Expression-bodied Methods
Introduction
Expression-bodied methods are a concise way to define methods in C# that consist of a single expression. Introduced in C# 6.0 and expanded in later versions, they provide a more elegant syntax for simple method implementations, making your code more readable and maintainable.
In this tutorial, we'll cover how expression-bodied methods work, when to use them, and see practical examples that demonstrate their benefits.
What Are Expression-bodied Methods?
Expression-bodied methods are a syntactic shorthand that allows you to replace the traditional method body (enclosed in curly braces) with a =>
operator followed by a single expression. The result of this expression is automatically returned from the method.
Traditional Method vs. Expression-bodied Method
Here's a comparison of traditional method syntax and expression-bodied syntax:
// Traditional method
public int Add(int a, int b)
{
return a + b;
}
// Expression-bodied method
public int Add(int a, int b) => a + b;
As you can see, the expression-bodied method is more concise and eliminates the need for the return
keyword and curly braces.
Basic Syntax and Usage
The basic syntax for an expression-bodied method is:
access_modifier return_type MethodName(parameters) => expression;
Let's look at different types of methods that can benefit from this syntax:
Instance Methods
public class Calculator
{
// Expression-bodied instance method
public int Add(int a, int b) => a + b;
public double CalculateArea(double radius) => Math.PI * radius * radius;
}
Static Methods
public class MathHelper
{
// Expression-bodied static method
public static int Square(int number) => number * number;
public static bool IsEven(int number) => number % 2 == 0;
}
Using Expression-bodied Methods with Different Return Types
Expression-bodied methods work with all return types:
Void Methods (C# 7.0+)
Starting with C# 7.0, you can use expression-bodied syntax for methods that don't return a value:
public class Logger
{
// Expression-bodied void method
public void LogMessage(string message) => Console.WriteLine($"LOG: {message}");
}
Methods Returning Complex Types
public class PersonFactory
{
public Person CreatePerson(string name, int age) => new Person { Name = name, Age = age };
}
Methods Returning Collections
public class NumberGenerator
{
public List<int> GetEvenNumbers(int count) =>
Enumerable.Range(1, count * 2).Where(n => n % 2 == 0).ToList();
}
Practical Examples
Let's explore some practical scenarios where expression-bodied methods are particularly useful:
Example 1: Data Transformation
public class UserService
{
public UserViewModel MapToViewModel(User user) =>
new UserViewModel
{
DisplayName = $"{user.FirstName} {user.LastName}",
Email = user.Email,
MemberSince = user.JoinDate.ToString("MMM yyyy")
};
}
Example 2: Validation Methods
public class InputValidator
{
public bool IsValidEmail(string email) =>
!string.IsNullOrEmpty(email) && email.Contains("@") && email.Contains(".");
public bool IsAdult(DateTime birthDate) =>
(DateTime.Now - birthDate).TotalDays > 365 * 18;
}
Example 3: LINQ-based Operations
public class ProductService
{
private List<Product> _products;
// Find products by category
public IEnumerable<Product> FindByCategory(string category) =>
_products.Where(p => p.Category == category);
// Get the average price
public decimal GetAveragePrice() => _products.Average(p => p.Price);
}
Complete Program Example
Let's see a complete program that demonstrates expression-bodied methods in action:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ExpressionBodiedMethodsDemo
{
class Program
{
static void Main(string[] args)
{
// Create a text processor and use its methods
var processor = new TextProcessor();
string sampleText = "Hello, expression-bodied methods!";
Console.WriteLine($"Original text: {sampleText}");
Console.WriteLine($"Word count: {processor.CountWords(sampleText)}");
Console.WriteLine($"Character count: {processor.CountCharacters(sampleText)}");
Console.WriteLine($"Uppercase: {processor.ToUpperCase(sampleText)}");
Console.WriteLine($"Reversed: {processor.Reverse(sampleText)}");
// Use statistics calculator
var numbers = new List<int> { 5, 2, 8, 9, 1, 7, 3, 6, 4 };
var stats = new StatisticsCalculator();
Console.WriteLine($"\nNumbers: {string.Join(", ", numbers)}");
Console.WriteLine($"Average: {stats.Average(numbers)}");
Console.WriteLine($"Minimum: {stats.Min(numbers)}");
Console.WriteLine($"Maximum: {stats.Max(numbers)}");
Console.WriteLine($"Sum: {stats.Sum(numbers)}");
Console.WriteLine($"Even numbers: {string.Join(", ", stats.GetEvenNumbers(numbers))}");
}
}
class TextProcessor
{
// All methods using expression-bodied syntax
public int CountWords(string text) =>
string.IsNullOrWhiteSpace(text) ? 0 : text.Split(new[] { ' ', '\t', '\n' }, StringSplitOptions.RemoveEmptyEntries).Length;
public int CountCharacters(string text) => text?.Length ?? 0;
public string ToUpperCase(string text) => text?.ToUpper();
public string Reverse(string text) =>
new string(text?.Reverse().ToArray() ?? Array.Empty<char>());
}
class StatisticsCalculator
{
// Calculate average of numbers
public double Average(List<int> numbers) => numbers.Any() ? numbers.Average() : 0;
// Get minimum value
public int Min(List<int> numbers) => numbers.Any() ? numbers.Min() : 0;
// Get maximum value
public int Max(List<int> numbers) => numbers.Any() ? numbers.Max() : 0;
// Calculate sum
public int Sum(List<int> numbers) => numbers.Sum();
// Get even numbers
public IEnumerable<int> GetEvenNumbers(List<int> numbers) =>
numbers.Where(n => n % 2 == 0);
}
}
Output:
Original text: Hello, expression-bodied methods!
Word count: 3
Character count: 32
Uppercase: HELLO, EXPRESSION-BODIED METHODS!
Reversed: !sdohtem deIdob-noisserpxe ,olleH
Numbers: 5, 2, 8, 9, 1, 7, 3, 6, 4
Average: 5
Minimum: 1
Maximum: 9
Sum: 45
Even numbers: 2, 8, 6, 4
Best Practices for Using Expression-bodied Methods
-
Keep it simple: Use expression-bodied methods for simple, one-line operations. If the logic becomes complex, use a traditional method body.
-
Readability matters: Only use expression-bodied methods when they improve readability. Sometimes a traditional method body is clearer, especially for beginners.
-
Ideal use cases:
- Simple calculations
- Property transformations
- Short LINQ queries
- Delegate implementations
- Condition checks
-
Avoid for complex logic: Don't use them for methods that contain multiple operations or complex logic.
When Not to Use Expression-bodied Methods
While expression-bodied methods are concise, they're not always the best choice:
// Not ideal for expression-bodied method - too complex
public List<Product> GetDiscountedProducts(List<Product> products, decimal discountPercentage) =>
products.Select(p => {
p.Price = p.Price * (1 - discountPercentage / 100);
p.IsOnSale = true;
p.LastUpdated = DateTime.Now;
return p;
}).ToList();
// Better as a traditional method
public List<Product> GetDiscountedProducts(List<Product> products, decimal discountPercentage)
{
var result = new List<Product>();
foreach (var product in products)
{
product.Price = product.Price * (1 - discountPercentage / 100);
product.IsOnSale = true;
product.LastUpdated = DateTime.Now;
result.Add(product);
}
return result;
}
Summary
Expression-bodied methods provide a concise syntax for defining simple methods in C#. They are particularly useful for:
- Methods that return a single expression
- Simple calculations and transformations
- Methods that delegate to other methods
- Short LINQ queries and operations
Benefits include:
- More concise code
- Improved readability for simple operations
- Less boilerplate for straightforward methods
Remember that the goal is to make your code more readable, not just shorter. Use expression-bodied methods when they enhance clarity, but don't hesitate to use traditional method bodies for more complex operations.
Additional Resources
Exercises
-
Convert the following traditional methods to expression-bodied methods:
csharppublic int Multiply(int a, int b) { return a * b; }
public string GetFullName(string first, string last) { return $"{first} {last}"; }
public bool IsPositive(int number) { return number > 0; } -
Create a
Circle
class with expression-bodied methods to calculate area, circumference, and diameter. -
Write a
StringHelper
class with expression-bodied methods for common string operations (counting vowels, reversing words, checking palindromes, etc.). -
Implement a simple calculator using expression-bodied methods for basic arithmetic operations.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)