Bracket Patterns in C# - P.1
Tags: csharp, patterns
Published: 2020-11-20 09:47:02

*Perhaps a month ago, I teased a coming post about bracket/delimiter/begin-end patterns in C#...*

# What is a bracket pattern?

If you have used OpenGL, you may remember code looking like:

```cpp
glBegin(GL_QUADS);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex2f(-0.5f, -0.5f);    
// ...
glEnd();
```

These patterns are not uncommon and they are, well - error prone. Ever accidentally left your front door open? That is how goes with pairing commands as above.

# Bracket patterns in C-sharp

In C# you may leverage `using` and `IDisposable`. However this is on the heavy side, primarily for safely managing resources.

I review lightweight alternatives - looking at increasingly more powerful variants.

## The basics

In the simplest case, we want a pattern *equivalent* to...

```cs
Begin();
DoSomething();
End();
```

A basic bracket pattern, then, is implemented as follows:

```cs
class Service{

    public Func<T> With{ get{
        Start();
        return End;
    }}

    void Start(){ ... }

    void End(T arg){ ... }

}
```

Enabling the following use:

```cs
With( DoSomething() );
```

Returning the `With` function as a property allows running code both *before* and *after* running the enclosed command.

One use case is with functional graphic APIs (such as OpenGL, and others...); Unity, for instance, provides the following API(\*):

(\*) *In places they now use `IDisposable`*

```cs
BeginHorizontalGroup();
Label("Hello");
EndHorizontalGroup();
```

Which then becomes:

```cs
HorizontalGroup( Label("Hello") );
```

And the pattern implementation:

```cs
public static class GUI{

    public static Func<object> With{ get{
        BeginHorizontalGroup();
        return End;
    }}

    void End(object arg) => EndHorizontalGroup();

}
```

As you see we are not doing any with the argument - our purpose here is only 'framing' the `Label()` command. Which brings us to the one constraint these patterns are sharing: `Label()` (and likewise framed commands) cannot return `void`.

Although I did use a `static` class this is not required; so, assuming the target API does not use globals either, thread safety may be preserved.

A common use case for bracket patterns is when building hierarchies and this may help designing articulate alternatives to the builder pattern.

In its most simple form the bracket pattern only supports one argument. What if (as makes sense with a horizontal group) we wanted to combine several commands? Then, use a *delegate*:

```cs
public class Service{

    public EndFunc With{ get{
        Start();
        return End;
    }}

    void Start(){ ... }

    delegate void EndFunc(params T[] args);

    void End(params T[] args){ ... }

}
```

The reason we need a delegate here is var-args (`...`) are not supported by any variant of `System.Func<...>`.

Back to the 'horizontal group' example, the above then enables the following syntax:

```cs
HorizontalGroup( 
    Label("Hello"), 
    Button("Tap to enter"),
);
```

If you go back to the OpenGL example, note how the `glBegin(GL_QUADS)` function allowed arguments. In the next session I'll be looking at a handy variant which cleanly separates arguments to the `begin` function from the enclosed items. 

Var-arg forms allocate memory; often the impact is negligible; when it's not there is an alternative, and I'll also review this in my next posting.

Happy Coding ~ 

<span>Photo by <a href="https://unsplash.com/@dancristianp?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Dan-Cristian Pădureț</a> on <a href="https://unsplash.com/s/photos/bracket?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></span>