C# 15 Union Types Explained Simply – A Better Way to Handle Multiple Return Types

C# keeps evolving to make code more expressive and safer. One of the most interesting additions in C# 15 is Union Types, which are currently available starting with .NET 11 Preview 2.

This feature has been available in other languages for a long time, and now it’s finally coming to C#. It helps developers clearly define values that can be one of several types — without losing type safety.

What Problem Do Union Types Solve?

In real-world applications, a method doesn’t always return a single type.

For example:

  • A service might return data or an error
  • A process might return success or validation issues

Until now, developers had to handle this in less-than-ideal ways:

  • Using object (not type-safe)
  • Creating base classes or interfaces
  • Implementing custom patterns like Result<T>

All of these work, but they either add complexity or reduce clarity.

What Are Union Types?

A union type allows a variable to hold one of a fixed set of types.

Instead of saying:

“This can be anything”

You say:

“This can only be one of these specific types”

This makes the code more predictable and easier to understand.

How Union Types Work in C#

With C# 15, you can define a union by listing the allowed types.

Then, when using the value, pattern matching is used to handle each possible case. The compiler ensures that all cases are handled properly, which reduces bugs and missed conditions.

C#
public record Success(string Message);
public record Failure(string Error);

public union OperationResult(Success, Failure);

OperationResult result = new Success("Order created successfully");

string output = result switch
{
    Success s => $"Success: {s.Message}",
    Failure f => $"Error: {f.Error}"
};

Console.WriteLine(output);
What’s happening here?
  • OperationResult can only be Success or Failure
  • No other types are allowed
  • The switch ensures both cases are handled
  • The compiler will warn if a case is missed

Benefits of Using Union Types

  • Better Type Safety: Only allowed types can be used. No unexpected values.
  • Clear API Design: The method clearly communicates what it can return.
  • Improved Readability: Anyone reading the code understands all possible outcomes.
  • Safer Pattern Matching: The compiler helps ensure every case is handled.

Real-World Use Cases

Union types can be very useful in everyday development.

API Responses

Return:

  • Success
  • Not found
  • Validation error
Domain Logic

Business operations can return:

  • Completed result
  • Business rule violation
File Processing

A file operation might return:

  • Processed result
  • Invalid format
  • Permission issue

In all these cases, unions make the intent clear and enforce correct handling.

Try It Yourself

If trying out union types, make sure the environment is set up for preview features.

Here’s what is needed:

  • Install the .NET 11 Preview SDK
  • Create a new project or update an existing one to target net11.0.
  • Enable preview language features by setting preview <LangVersion>preview</LangVersion>

Support in Visual Studio is still catching up. The feature is expected in upcoming Insiders builds, and it is already available in the C# Dev Kit Insiders version.

Early Preview Note

Since this feature is still in an early preview, some required types are not yet included in the runtime. That means a small setup step is needed.

Add the following definitions manually in the project:

C#
namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct,
        AllowMultiple = false)]
    public sealed class UnionAttribute : Attribute;

    public interface IUnion
    {
        object? Value { get; }
    }
}

These act as placeholders for now. In future .NET previews, they will be included by default, so this extra step will not be necessary.

Summary

C# 15 Union Types introduce a cleaner way to handle multiple possible outcomes in code. Instead of relying on loosely typed approaches or custom patterns, developers can now define a fixed set of allowed types.

This improves clarity, safety, and overall code quality.

Takeaways

  • Union types allow a value to be one of several defined types
  • They replace common patterns like object or custom result wrappers
  • They improve type safety and readability
  • Pattern matching ensures all cases are handled
  • Available in .NET 11 Preview 2, still evolving

Found this article useful? Share it with your network and spark a conversation.