Introducing: C# Pipe Extensions!
Tags: csharp, dotnet, functional, showdev
Published: 2021-05-18 00:33:54

tl;dr - I've recreated the forward pipe operator from F# to be used in C#. Visit the [NuGet page](https://www.nuget.org/packages/WinstonPuckett.PipeExtensions/1.0.0#) to start using it yourself.

# Why does this package exist?

Local variables make clean code look cluttered. It's hard to see the flow of operation when you need to refer back to the variables being used. For instance, let's look at this code:

```csharp
// Example One
public void ExecuteUserFlow(Input input)
{
    var model = Query(input);
    Validate(model);
    var outputModel = Transform(model);
    Submit(outputModel);
}
```

What you want to see is the flow of operations:

1. Query
1. Validate
1. Transform
1. Submit

Because you know the flow of operations, every local variable is noise.

You *could* deal with this by calling the functions from the last statement inward...

```csharp
// Example Two
public void ExecuteUserFlow(Input input)
{
    Submit(
        Transform(
            Validate(
                Query(
                    input))));
}
```

...but I think you'll agree that this decreases the readability significantly. At the end of the day, it would be better to create a bit of noise by using local variables than to use the confusing syntax above.

But what if there was a third option?

# Learning from functional languages

Functional languages often lend themselves well to a compact syntax. I fell in love with F# because of its [Forward Pipe Operator (|>)](https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/functions/#function-composition-and-pipelining).

The first example above is the preferred way to write code because it allows a developer to read the statement from top to bottom. The second is better because it allows you to not use any local variables. A forward pipe operator allows you to read from top to bottom without local variables by passing the result of the last function as an input to the next. 

Here is an example of the forward pipe operator in F#:

```fsharp
input
  |> Query
  |> Validate
  |> Transform
  |> Submit
```

There is also a similar operator in Clojure, but I don't know Clojure that well, so I'll just leave a link to [its version of the forward pipe operator, ->>](https://clojuredocs.org/clojure.core/-%3E%3E).

This sort of syntax, which gives you a top/down, compact way to specify sequence is one of my favorite ways to make code more readable. Having a forward pipe operator in C# would be amazing.

# Introducing WinstonPuckett.PipeExtensions!

I've made a package to do just that! It's free, open source, and available on NuGet.

Here are the major features:

- Uses extension methods.
- Works on any object.
- You can chain async/non-async methods in any order without any hassle.

## Examples

Simple example:

```csharp
public void ExecuteUserFlow(Input input)
{
    input
      .Pipe(Query)
      .Pipe(Validate)
      .Pipe(Transform)
      .Pipe(Submit);
}
```

Use an async method:

```csharp
public async Task ExecuteUserFlow(Input input)
{
    await input
      .Pipe(Query)
      .Pipe(Validate)
      .Pipe(Transform)
      .PipeAsync(SubmitAsync); // Notice this async method
}
```

Mix async and non-async methods:

```csharp
public async Task ExecuteUserFlow(Input input)
{
    await input
        .Pipe(Query)
        .PipeAsync(ValidateAsync)
        .PipeAsync(Transform) 
        .PipeAsync(SubmitAsync);

    // Notice that transform is not 
    // async, but Pipe awaits a task 
    // from ValidateAsync, so PipeAsync 
    // is required.

    // You must always use PipeAsync
    // after your first async method.
}
```

## How it works inside

If you're curious, the code to implement this is incredibly simple. In the basic form, you take in an input of type T and a function which operates on T and returns U. Then you return the result of calling that function.

```csharp
public static U Pipe<T, U>(this T input, Func<T, U> func)
{
    return func(input);
}
```

# NuGet / GitHub links

- [NuGet](https://www.nuget.org/packages/WinstonPuckett.PipeExtensions/1.0.0#)
- [Github](https://github.com/winstonpuckett/WinstonPuckett.PipeExtensions)

# There are two requests to make this a first-class feature of C#

If you like this concept, please support these requests to make the forward pipe operator part of the language. I have no affiliation with either author, but I would love to see an even more succinct syntax than what my package can provide.

- [Proposal: forward pipe operators #74](https://github.com/dotnet/csharplang/discussions/74)
- [Proposal: Pipe-forward operator #96](https://github.com/dotnet/csharplang/discussions/96)