Continuation<TFail, TSuccess>
This type represents a value that allows chainable operations with methods and operations.
Instances of Continuation<TFail, TSuccess>
contains an instance of TSuccess
or TFail
similar to Either values.
However, the Either
type focus on encapsulate one of two possible values, the Continuation
is more focused to creates a mechanism of a sophisticated, powerful and idiomatic flow to compose your methods.
Because of the nature of this type, this type doesn't implements the Match2
method. Instead of it, this class do have the powerful Then
and Catch
methods. These methods allows to create a continuous flow to successful and unsucessful operations.
Through these two methods the Continuation
struct can generate a pipeline with two or more functions by connecting the output of one function as a parameter to the next function in the pipeline flow.
If you have a f function defined by A -> B
and a g function defined by B -> C
, you can create a new fg function as A -> C
connecting the returns of f as a g input.
The Continuation
values can assume two different states:
Success - When it contains a
TSuccess
value;Fail - When it contains a
TFail
value.
Properties
Name
Type
Description
IsSuccess
bool
Returns true when the result value is a TSuccess value. Otherwise, returns false.
IsFail
bool
Returns true when the result value is a TFail value. Otherwise, returns false.
Constructors
Parâmetros
Retorno
Descrição
TSuccess success
Continuation<TFail, TSuccess>
Initialize a new instance of Continuation<TFail, TSuccess> with a TSuccess value.
TFail fail
Continuation<TFail, TSuccess>
Initialize a new instance of Continuation<TFail, TSuccess> with a TFail value.
Methods
Name
Parameters
Returns
Description
Return
TSuccess success
Continuation<TFail, TSuccess>
Initialize a new instance of Continuation<TFail, TSuccess> with a TSuccess value.
Return
TFail fail
Continuation<TFail, TSuccess>
Initialize a new instance of Continuation<TFail, TSuccess> with a TFail value.
Match
Func<TSuccess,TResult> methodWhenSuccess
Func<TFail, TResult> methodWhenFail
TSuccess
This allows a sophisticated way to apply some method for Continuation<TFail, TSuccess> values without having to check for the existence of a TFail or TSuccess value.
Match
Action<TSuccess> methodWhenSuccess
Action<TFail> methodWhenFail
Unit
This allows a sophisticated way to apply some method for Continuation<TFail, TSuccess> values without having to check for the existence of a TFail or TSuccess value.
Then
Func<TSuccess, Continuation<TFail, TSuccess>> thenMethod
Continuation<TFail, TSuccess>
This allows a sophisticated and powerful way to apply some method in order to compose an operation with different functions.
When the current Continuation<TFail, TSuccess> IsSuccess the thenMethod is applied. Otherwise, returns itself until encounter a Catch function.
Then
Func<TSuccess, Continuation<TFail, TNewSuccess>> thenMethod
Continuation<TFail, TNewSuccess>
This allows a sophisticated and powerful way to apply some method in order to compose an operation with different functions.
When the current Continuation<TFail, TSuccess> IsSuccess the thenMethod is applied. Otherwise, returns itself until encounter a Catch function.
Then
Func<TParameter, TSuccess, Continuation<TFail, TNewSuccess>> thenMethod
TParameter parameter
Continuation<TFail, TNewSuccess>
This allows a sophisticated and powerful way to apply some method in order to compose an operation with different functions.
When the current Continuation<TFail, TSuccess> IsSuccess the thenMethod is applied. Otherwise, returns itself until encounter a Catch function.
Catch
Func<TFail, Continuation<TFail, TSuccess>> catchMethod
Continuation<TFail, TSuccess>
This allows a sophisticated and powerful way to apply some method in order to compose an operation with different functions.
When the current Continuation<TFail, TSuccess> IsFail the catchMethod is applied. Otherwise, returns itself until encounter a Then function.
Catch
Func<TFail, Continuation<TNewFail, TSuccess>> catchMethod
Continuation<TNewFail, TSuccess>
This allows a sophisticated and powerful way to apply some method in order to compose an operation with different functions.
When the current Continuation<TFail, TSuccess> IsFail the catchMethod is applied. Otherwise, returns itself until encounter a Then function.
Finally
Action finallyMethod
Continuation<TFail, TSuccess>
This provides a way for code that must be executed once the Continuation<TFail, TSuccess> has been dealt with to be run whether the was fulfilled successfully or failed.
This lets you avoid duplicating code in both the Then and Catch methods.
Finally
Action< Either<TFail,TSuccess> > finallyMethod
Continuation<TFail, TSuccess>
This provides a way for code that must be executed once the Continuation<TFail, TSuccess> has been dealt with to be run whether the was fulfilled successfully or failed.
This lets you avoid duplicating code in both the Then and Catch methods.
Merge
Func<TSuccess, Continuation<TNewFail,TNewSuccess>> mergeMethod
Continuation<( Option<TFail>, Option<TNewFail>), (TSuccess, TNewSuccess)>
This allows a powerful way to merge two different Continuations in a single grouped Continuation<(TFail, TNewFail), (TSuccess, TNewSuccess)>.
Operators Overload
Operator
Parameters
Returns
Description
Implicit cast
TSuccess success
Continuation<TFail, TSuccess>
Initialize a new instance of Continuation<TFail, TSuccess> with a TSuccess value.
Implicit cast
TFail fail
Continuation<TFail, TSuccess>
Initialize a new instance of Continuation<TFail, TSuccess> with a TFail value.
Implicit cast
Continuation<TFail, TSuccess>
Option<TFail>
Creates an Option<TFail> of TFail value by Success property of the Continuation<TFail, TSuccess> value.
Implicit cast
Continuation<TFail, TSuccess>
Option<TSuccess>
Creates an Option<TSuccess> of TSuccess value by Success property of the Continuation<TFail, TSuccess> value.
Implicit cast
Either<TFail, TSuccess>
Continuation<TFail, TSuccess>
Creates a Continuation<TFail, TSuccess> from an Either<TFail, TSuccess> value.
Greater than (>)
Continuation<TFail, TSuccess>
Func<TSuccess, Continuation<TFail, TSuccess>> thenMethod
Continuation<TFail, TSuccess>
Executes the Then method to create a pipeline flow.
Greater or equal (>=)
Continuation<TFail, TSuccess>
Func<TSuccess, Continuation<TFail, TSuccess>> catchMethod
Continuation<TFail, TSuccess>
Executes the Catch method to create a pipeline flow.
WARNING
Because of languages limitations the
Continuation
type also implements an overload to (<
) and (<=
). But if any of these operators raises a newNotSupportedException
.
Usage
You can use a Continuation
value in so many different ways, usually the creation of a Continuation
value indicates that a series of functions will be executed as a composition.
Creating a continuation value
You can use the constructor to create option values in IsFail or IsSuccess states, according its parameter.
Constructors
You can use the Return
static method as well.
The Return static method
Finally the simplest version: implict cast. Because of this feature you don't need to worry about any kind of syntax, you just create the value as regular types.
Implicit cast
Through this implicit cast you can creates new option values by using regular return commands, in this particular case is very common to use two different return commands with different types.
See the code bellow:
It can looks weird at first, by having two returns with two different types, but actually both returns will creates a new Continuation
value. But instead of deal with it, Tango pass this responsibility to C#.
Getting value from an continuation
Like the other containers types it is necessary to use the Match method to get the encapsulated value of an Continuation
type.
In this type you can also get the value by an implicit cast to an Option of either TFail or TRight. In this particular case the option value will receive one of these two types and creates an value according to the Continuation
value.
Implict cast to an Option
WARNING
Even when the implicit cast was made for the correct type the option value can receive an None value, because the restrictions of option value.
This case will occurs when the Either encapsulated value is equals to null or its default.
You can also uses the Match
method. This method receive two different functions as parameters, one for each case: Success
and Fail
states
Match with named parameters
The first method is executed when the continuation IsSuccess
, because of it, this method receive a TSuccess
value as parameter (int
in this example).
The second method is executed when the continuation IsFail
, because of it, this method receive a TFail
value as parameter (bool
in this example).
Just like Either types does.
Finally, these two functions are just regular parameters, so, you can omit the its names.
Match
Besides that, you can also apply some transformation in value before got it, like square the value:
You can also returns any value in IsFail
case, in the previous examples were used the zero value, but it isn't obrigatory.
The Match
method can creates any type of value, even types that are not defined as TFail or TSuccess.
Match to create a new result
There's no way to compare two different Continuation
values simultaneously.
Creating Pipelines
The main value of the Continuation
type is its capacity to creates clean and sophisticated methods in a pipeline flow by using Then
and Catch
methods.
You can encapsulate an integer value in a Continuation
type and increasing this value in a pipeline flow, as showed by the following example.
Using Then to increase a value
Initially, the Continuation
structure contained the value 5, after the first Then
method the value was increased by 5. It occurs because the encapsulated value is passed as a parameter to the anonymous function described by value => value + 5
.
Finally, the result of the operation described by the first function (10) is passed to the second anonymous function: value => value + 10
creating the final result (20).
When Then isn't executed
When the Continuation
state IsFail
neither of the sThen
methods are executed, it performs just a bypass.
In this particular case, you can use the implicit cast feature to get an Option<bool>
to deal with the fail of the process.
Implicit cast to get the fail result
It is extremely important to notice that there's a real situation where the fail occurs inside the pipeline flow.
When it occurs, all of the Then
methods described bellow the fail function will be ignored.
When the fail occurs inside the pipeline flow
The previous example shows a function that will creates a fail in the second Then
method. Because of this, the third Then
method will performs just a bypass.
You can use the Catch
method to create methods to deal with Fail
values.
Using Catch to deal with fails
When a Continuation
value contains a TFail
value it will be ignored by the Then
methods, that's the main point about Catch
methods, it a similar method, but in this case, it will execute when the value is TFail
and will performs a bypass when the value is `TSuccess´.
Like the Then
methods, Catch
methods are also chainables.
Chained Catches
Avoid repeat yourself by using Finally
Sometimes you need to perform an action no matter the Continuation
value result contains, either a TFail
or TSuccess
value. That's the main point about Finally
methods, it is similar to Then
and Catch
, but in this case, it always will execute.
Other notorius difference between Finally
and the other two methods, is your function parameter. In this case, you can use an Action without any argument. It will be executed and the Continuation
will be returned to keep the Continuation
flow.
Usually the Finally
method will be the last method of a Continuation
flow and cause a side effect, so, be careful and keep your eye on it.
Another major difference between this method and the two previous ones, is the fact that you're not able to modify the Continuation
value. Actually you can access the values by using an overload of Finally that receives an Action<Either<TFail, TSuccess>>
type as argument.
Like Then
and Catch
methods, Finally
methods are also chainables.
Merging two pipelines in a single one
This isn't a common operation, but sometimes you need to merge two different Continuation
pipelines to complete your use case. In order to make it easy, you can use the Merge
method.
The argument function of this method receive the entire Continuation<TFail, TSuccess>
itself as argument and need to return an brand new Continuation<TNewFail, TNewSuccess>
. The Merge
return is a new grouped Continuation<(Option<TFail>, Option<TNewFail>), (TSuccess, TNewSuccess)>
.
This new Continuation
will be in Success state only when the two previous ones are also in this state, otherwise it will be in Fail state.
You can continue your pipeline, but now, you need to access the Item
properties, since the values were grouped.
The new Continuation
fail types are treated as Option
values, because there's no guarantee of wich error was occured.
Chaining methods with pipeline operator
The .NET functional programming language, F#, has an operator to performs these pipeline flows.
This operator are defined by |>
as pipe-foward and <|
as reverse pipe or pipe-backward.
With these operators you can perform an elegant pipeline flow like this:
Unfortunatelly there's no way to create new operators for your C# code. However, is totally possible to overload the current operators.
With this mindset, Tango created some overloads to >
and >=
operators to work as pipelines, similar to F# syntax.
Instead of performs a comparison as its default behavior, these operations works as Then
and Catch
methods.
Therefore, is fully possible to creates pipelines replacing Then
for >
and Catch
for >=
.
Replacing Then by >
Replacing Then and Catch by >
and >=
WARNING
There are some limitations by usign operators: 1. Different from F#, is not possible to performs a reverse pipe; 2. It's possible to replace the
Then
andCatch
methods with the operators only when the resulting value is the same type as the currentContinuation
. There's no way to overload an operator with generics.
When you want to change the Continuation types
Both Then
and Catch
methods contains overloads that implements the possibility to create a new Continuation
type, this way is possible to change the TSuccess
and TFail
throughout the pipeline.
It is important to say that isn't necessary using the generics notation: Then<targetType>
, but you can use it, if you want to.
Get the final result
Usually, after the pipeline you'll need to get the final value, or handle the eventually failures at least.
You can use the Match
method after all Then
and Catch
methods.
Last updated
Was this helpful?