C#
C# 7
return values
programming
software development

How to return multiple values in C 7?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

C# 7 made returning multiple values much cleaner by adding tuple syntax to the language. Instead of defining a throwaway class or relying on several out parameters, you can return a small group of related values directly from a method.

Return a Tuple

The core syntax is simple: declare the method return type as a tuple and return matching values.

csharp
1using System;
2
3public class Example
4{
5    public static (int sum, int product) Calculate(int a, int b)
6    {
7        return (a + b, a * b);
8    }
9
10    public static void Main()
11    {
12        var result = Calculate(3, 4);
13        Console.WriteLine(result.sum);
14        Console.WriteLine(result.product);
15    }
16}

The names sum and product are optional but strongly recommended. Named tuple members make the result easier to read and prevent code from turning into a series of Item1, Item2, and Item3 accesses.

Deconstruct the Return Value

If the caller wants the values as separate local variables, deconstruction is even clearer.

csharp
1using System;
2
3public class Program
4{
5    static (string firstName, string lastName) SplitName(string fullName)
6    {
7        string[] parts = fullName.Split(' ', 2);
8        return (parts[0], parts.Length > 1 ? parts[1] : "");
9    }
10
11    static void Main()
12    {
13        var (firstName, lastName) = SplitName("Ada Lovelace");
14        Console.WriteLine(firstName);
15        Console.WriteLine(lastName);
16    }
17}

This style is compact and expressive when the returned values belong together conceptually but do not justify a separate type.

Compare Tuples with Older Approaches

Before C# 7, the most common alternatives were out parameters and custom classes or structs.

out parameters still work:

csharp
1public static bool TryDivide(int a, int b, out int result)
2{
3    if (b == 0)
4    {
5        result = 0;
6        return false;
7    }
8
9    result = a / b;
10    return true;
11}

This is appropriate for TryParse style methods where success and output are tightly linked. For general "return several pieces of data" cases, tuples are easier to read.

A custom type is better when the returned data has behavior, validation rules, or long-term meaning in your domain. Tuples are best for lightweight groupings, not for every public API.

When a Custom Type Is Better

If the method returns many fields, or the result will be passed around widely, a named class, record, or struct usually communicates intent better than a tuple.

For example, this:

csharp
public record CalculationResult(int Sum, int Product, int Difference);

can be better than returning a long tuple because the result has a stable identity and self-documenting meaning.

A practical rule is:

  • use tuples for short-lived helper results
  • use out parameters for TryXxx patterns
  • use a custom type when the result is part of the domain model or public contract

Performance and Readability

Value tuples are lightweight and generally efficient for typical application code. In practice, readability matters more than tiny performance differences here. The bigger mistake is choosing a form that hides meaning from callers.

If consumers keep forgetting what Item1 and Item2 represent, the code is telling you to add names or introduce a real type.

Common Pitfalls

  • Returning unnamed tuples and forcing callers to use Item1 and Item2, which hurts readability.
  • Replacing every small type with tuples. Some results deserve a named type because they carry domain meaning.
  • Using tuples where a TryXxx method with out parameters is the established .NET pattern.
  • Returning too many tuple elements. Large tuples quickly become harder to understand than a small class or record.
  • Assuming tuple field names are a full substitute for good method names and documentation.

Summary

  • In C# 7, tuples are the usual way to return multiple values from a method.
  • Named tuple members make results much easier to consume than Item1 style access.
  • Deconstruction lets callers unpack tuple values into separate variables cleanly.
  • 'out parameters still fit TryXxx patterns well.'
  • Use a custom type when the returned data has lasting semantic meaning.

Course illustration
Course illustration

All Rights Reserved.