Functional C#

{coding}Sight
2 min readAug 29, 2018

--

C# is a multi-paradigm programming language. Recently, the course has been set towards new functional constructions in C#. We can go further and add other extension methods that allow writing less code without ‘climbing’ in the F# territory.

PipeTo

As Pipe Operator is not going to be included in the upcoming next release, we can write the code using the method.

public static TResult PipeTo<TSource, TResult>(
this TSource source, Func<TSource, TResult> func)
=> func(source);

Imperative variant

public IActionResult Get()
{
var someData = query
.Where(x => x.IsActive)
.OrderBy(x => x.Id)
.ToArray();
return Ok(someData);
}

With PipeTo

public IActionResult Get() => query
.Where(x => x.IsActive)
.OrderBy(x => x.Id)
.ToArray()
.PipeTo(Ok);

As you can see, in the first variant, I needed to cast a look back at a the variable declaration and then proceed to Ok, while with PipeTo, the execution flow is running strictly left to right, top to bottom.

Either

In the real world, there are more branching algorithms, rather than the linear ones:

public IActionResult Get(int id) => query
.Where(x => x.Id == id)
.SingleOrDefault()
.PipeTo(x => x != null ? Ok(x) : new NotFoundResult(“Not Found”));

It does not look so good anymore. Let’s fix it using the Either method:

public static TOutput Either<TInput, TOutput>(this TInput o, Func<TInput, bool> condition,
Func<TInput, TOutput> ifTrue, Func<TInput, TOutput> ifFalse)
=> condition(o) ? ifTrue(o) : ifFalse(o);

public IActionResult Get(int id) => query
.Where(x => x.Id == id)
.SingleOrDefault()
.Either(x => x != null, Ok, _ => (IActionResult)new NotFoundResult(“Not Found”));

Add a null check overload:

public static TOutput Either<TInput, TOutput>(this TInput o, Func<TInput, TOutput> ifTrue,
Func<TInput, TOutput> ifFalse)
=> o.Either(x => x != null, ifTrue, ifFalse);

public IActionResult Get(int id) => query
.Where(x => x.Id == id)
.SingleOrDefault()
.Either(Ok, _ => (IActionResult)new NotFoundResult(“Not Found”));

Unfortunately, the type inference in C# is not perfect. That’s why I had to add an explicit cast to IActionResult.

Do

Get methods of controllers are not supposed to create side effects. However, sometimes they are really needed.

public static T Do<T>(this T obj, Action<T> action)
{
if (obj != null)
{
action(obj);
}

return obj;
}

public IActionResult Get(int id) => query
.Where(x => x.Id == id)
.Do(x => ViewBag.Title = x.Name)
.SingleOrDefault()
.Either(Ok, _ => (IActionResult)new NotFoundResult(“Not Found”));

With such code organization, it will be impossible to miss this effect with Do during code review. Though, using DO is a point at issue.

Liked the article? Continue reading here — https://bit.ly/2BWni6k.

Thank you for your time!

--

--

{coding}Sight
{coding}Sight

Written by {coding}Sight

Awesome blog focused on databases and Microsoft, .NET and cloud technologies. http://codingsight.com/

No responses yet