Using Extension methods as Decorators in C#.

Quick Functional Refactorings in C#

Dimitris Papadimitriou
2 min readJul 17, 2022

--

function follows form.

This will be Quick, and i want you to just grab the syntax.(Source)

Lets say we have this class:

public class OperationManager<T, R> 
{
public async Task<R> OperationAsync(T t) => {...};
}

I can add this extension method :

public static partial class FuntionalExtensions
{

public static Task<T> AddDebugLogging<T>(this Task<T> @this) =>
@this.ContinueWith((task) =>
{
var result = task.Result;
Debug.WriteLine(result);
return result;
});

}

and grab the result intermediately and write it in the debug log. In order to use this, instead of writing:

var result = await operationManager.OperationAsync(1);

you can write :

var result = await operationManager.OperationAsync(1)
.AddDebugLogging();

What this have to do with decorator pattern you might ask.

Optional

Abstract The log

Next step, Gradual improvements. What can i abstract. we can overload the extension method and abstract the log:

public static Task<T> AddDebugLogging<T>(this Task<T> @this, Action<T> action) =>
@this.ContinueWith(continuationFunction: (task) =>
{
var result = task.Result;
action(result);
return result;
});

Now we write :

var result1 = await operationManager.OperationAsync(1)
.AddDebugLogging(x => Debug.WriteLine(x));

[Note: When you abstract away, you should remember to rename things to match the change in abstraction, so we should probably call the method differently ???] . Depending on the Seniority you can immediately get the feel that this extension is to powerful (because it allows access to the whole result) and someone will probably abuse it. This leads to the next refactoring move etc.

--

--