Skip to content
David Arno edited this page Jun 27, 2016 · 1 revision

ValueOrError

SuccincT.Options.ValueOrError

Provides a special-case union of two string values: one representing a value; the other an error. For use in situations where a string return type is needed, by throwing exceptions isn't desirable.


Construction

Instances of ValueOrError cannot be created directly using new. As both possible values are of type string, the constructor would need two parameters and messy null passing, a boolean parameters or similar. Instead use the two static methods WithValue() and WithError().

WithValue()

    public static ValueOrError WithValue(string value)

Creates an instance of ValueOrError holding a value. If value is null, an ArgumentNullException will be thrown.

WithError()

    public static ValueOrError WithError(string error)

Creates an instance of ValueOrError holding an error. If error is null, an ArgumentNullException will be thrown.

Equality

ValueOrError is a class, not a struct, but it overrides both Equals and the == & != operator pair, so instances use value comparison for equality. The following rules apply to equality:

  • If an instance of ValueOrError holds a value, then it will equal another instance if that also hold a value and that value has the same string content.
  • If an instance of ValueOrError holds an error, then it will equal another instance if that also hold an error and that error has the same string content.

This can be expressed this in code with the following.

var valA = ValueOrError.WithValue("abc");
var valB = ValueOrError.WithValue("abc");
var valC = ValueOrError.WithValue("def");
var errA = ValueOrError.WithError("abc");
var errB = ValueOrError.WithError("abc");
var errC = ValueOrError.WithError("def");

// The following expressions are all true:
valA == valA
valA == valB
valB != valC
valA.Equals(valA)
valA != errA
errA == errA
errA == errB
errB != errC
errA.Equals(errB)

Functional Use

ValueOrError uses Succinc<T>'s pattern matching capabilities to perform an action or generate a result according to its value/error state. Two versions of the match method are directly supported by ValueOrError:

Match()

    public ValueOrErrorMatcher<T> Match()

Match() supports the construction of pattern matches and actions (void methods) to invoke upon match. The pattern must be terminated with Exec().

The format of an option match pattern is as follows:

option.Match()
      .Value()<optional guard>.Do(value => action on value)
      .Error()<optional guard>.Do(error => action on error)
      [.Else(option => action when no match) |
       .IgnoreElse()]
      .Exec()

Value() can take an optional guard of two forms:

.Value().Of(value1).Or(value2).Or(value3)...Do(value => action on value)
.Value().Where(value => boolean expression).Do(value => action on value)

Multiple Value() expressions may be defined. Each is compared in turn again the value (assume there is one) until a match is found. The action is then invoked and no further matching occurs.

Error() can also take an optional guard of two forms:

.Error().Of(value1).Or(value2).Or(value3)...Do(error => action on error)
.Error().Where(value => boolean expression).Do(error => action on error)

Multiple Error() expressions may be defined. Each is compared in turn again the value (assume there is one) until a match is found. The action is then invoked and no further matching occurs.

The Else action is used if no match was found. The ValueOrError itself is passed as a parameter to the associated action. If no action is required when no match occurs, IgnoreElse can be used instead.

If no match is found, and no Else() or IgnoreElse is defined, a SuccincT.PatternMatchers.NoMatchException will be thrown

Match<TResult>()

    public ValueOrErrorMatcher<T, TResult> Match<T>()

Match<T>() supports the construction of pattern matches and functions returning a TResult to invoke upon match. The pattern must be terminated with Result().

The format of an option match pattern is as follows:

option.Match<T>()
      .Value()<optional guard>.Do(value => func resulting in a T))
      .Error()<optional guard>.Do(error => func resulting in a T))
      .Else(option => no match func resulting in a T)
      .Result()

Value() can take an optional guard of two forms:

.Value().Of(value1).Or(value2).Or(value3)...Do(value => func resulting in a T))
.Value().Where(value => boolean expression).Do(value => func resulting in a T))

Multiple Value() expressions may be defined. Each is compared in turn again the value (assume there is one) until a match is found. The function is then invoked and no further matching occurs.

Error() can also take an optional guard of two forms:

.Error().Of(value1).Or(value2).Or(value3)...Do(error => func resulting in a T))
.Error().Where(value => boolean expression).Do(error => func resulting in a T))

Multiple Error() expressions may be defined. Each is compared in turn again the value (assume there is one) until a match is found. The function is then invoked and no further matching occurs.

The Else function is used if no match was found. The option itself is passed as a parameter to the associated function.

If no match is found, and no Else() defined, a SuccincT.PatternMatchers.NoMatchException will be thrown

Imperative Use

As an alternative to using an option in a functional style, its value can be directly accessed by more traditional, imperative style C# code. three read-only properties are provided for this purpose. In addition, ToString() is overridden to handle the dual-state nature of its values.

HasValue

public bool HasValue { get; }**

True if the ValueOrError has a value; false if it's an error.

Value

public string Value { get; }

If HasValue is true, this will return the value held. Otherwise it will throw an InvalidOperationException.

Error

public string Error { get; }

If HasValue is false, this will return the error held. Otherwise it will throw an InvalidOperationException.

ToString()

public override string ToString()

Returns Value of <the value held> or Error of <the error held> depending on with a value or error is held, respectively.

Clone this wiki locally