/// <summary> /// Converts a single result option to another option based on its contents. /// </summary> /// <remarks> /// <para> /// This method is implemented using deferred execution; the query represented by this method /// is not performed until the contents of the returned option are resolved, such as by enumeration. /// </para> /// </remarks> /// <typeparam name="TSource">The element type of <paramref name="source"/>.</typeparam> /// <typeparam name="TResult">The element type of the result option for this conversion.</typeparam> /// <param name="source">A source single result option.</param> /// <param name="ifZero"> /// A function to produce the result if <paramref name="source"/> represents a result of zero elements. /// </param> /// <param name="ifOne"> /// A function to produce the result if <paramref name="source"/> represents a result of one /// element, which accepts that element as a parameter. /// </param> /// <param name="ifMoreThanOne"> /// A function to produce the result if <paramref name="source"/> represents a result of more /// than one element. /// </param> /// <returns> /// An option equivalent to the result of calling <paramref name="ifZero"/>, <paramref /// name="ifOne"/>, or <paramref name="ifMoreThanOne"/> if <paramref name="source"/> /// represents a result of zero, one, or more than one element, respectively. /// </returns> /// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception> /// <exception cref="InvalidOperationException"> /// <paramref name="ifZero"/> is <see langword="null"/> and <paramref name="source"/> /// represents a result of zero elements, or <paramref name="ifOne"/> is <see /// langword="null"/> and <paramref name="source"/> represents a result of one element, or /// <paramref name="ifMoreThanOne"/> is <see langword="null"/> and <paramref name="source"/> /// represents a result of more than one element. /// </exception> public static IOpt <TResult> MatchOpt <TSource, TResult>(this ISingleResultOpt <TSource> source, Func <Opt <TResult> > ifZero = null, Func <TSource, Opt <TResult> > ifOne = null, Func <Opt <TResult> > ifMoreThanOne = null) { if (source == null) { throw new ArgumentNullException(nameof(source)); } return(Opt.DeferRaw(() => source.Match(ifZero, ifOne, ifMoreThanOne))); }
/// <summary> /// Immediately computes the result of any deferred computation represented by a single /// result option and returns a new single result option representing the final result. /// </summary> /// <param name="source">A source single result option.</param> /// <returns> /// A single result option representing the final result of any deferred computation /// represented by <paramref name="source"/>. /// </returns> /// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception> public static ISingleResultOpt ForceSingleResultOpt(this ISingleResultOpt source) { if (source == null) { throw new ArgumentNullException(nameof(source)); } return(source.ToFixedSingleResultOpt()); }
/// <summary> /// Converts a single result option to another option, substituting a specified option if /// this option represents more than one result. /// </summary> /// <typeparam name="TSource">The element type of <paramref name="source"/>.</typeparam> /// <param name="source">A source single result option.</param> /// <param name="replacement"> /// An option to produce the result if <paramref name="source"/> represents a result of more /// than one element. /// </param> /// <returns> /// An option equivalent to <paramref name="source"/>, if it represents a result of zero or /// one element; otherwise, an option equivalent to <paramref name="replacement"/>. /// </returns> /// <exception cref="ArgumentNullException"> /// <paramref name="source"/> or <paramref name="replacement"/> is <see langword="null"/>. /// </exception> public static IOpt <TSource> ReplaceIfMoreThanOne <TSource>(this ISingleResultOpt <TSource> source, IOpt <TSource> replacement) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (replacement == null) { throw new ArgumentNullException(nameof(replacement)); } return(Opt.DeferRaw(() => ReplaceIfMoreThanOneImmediate(source, replacement))); }
/// <summary> /// Converts a single result option to another option, substituting the result of a callback /// if this option represents more than one result. /// </summary> /// <typeparam name="TSource">The element type of <paramref name="source"/>.</typeparam> /// <param name="source">A source single result option.</param> /// <param name="replacementFactory"> /// A function to produce the result if <paramref name="source"/> represents a result of more /// than one element. /// </param> /// <returns> /// An option equivalent to <paramref name="source"/>, if it represents a result of zero or /// one element; otherwise, an option equivalent to the result of calling <paramref name="replacementFactory"/>. /// </returns> /// <exception cref="ArgumentNullException"> /// <paramref name="source"/> or <paramref name="replacementFactory"/> is <see langword="null"/>. /// </exception> public static IOpt <TSource> ReplaceIfMoreThanOne <TSource>(this ISingleResultOpt <TSource> source, Func <IOpt <TSource> > replacementFactory) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (replacementFactory == null) { throw new ArgumentNullException(nameof(replacementFactory)); } return(Opt.DeferRaw(() => ReplaceIfMoreThanOneImmediate(source, Opt.DeferRaw(() => Opt.Fix(replacementFactory()))))); }
private static bool SingleResultOptEqualsObjectRaw(ISingleResultOpt a, object b) { if (b is ISingleResultOpt sb) { return(SingleResultOptEqualsSingleResultOpt(a, sb)); } else if (b is IOpt pb) { return(SingleResultOptEqualsPlainOpt(a, pb)); } else { return(false); } }
/// <summary> /// Implements equality for an ISingleResultOpt. /// </summary> internal static bool SingleResultOptEqualsObject(ISingleResultOpt _this, object obj) { if (_this == obj) { return(true); } else if (_this == null || obj == null) { return(false); } else { return(SingleResultOptEqualsObjectRaw(_this, obj)); } }
/// <summary> /// Converts a single result option to another value based on its contents. /// </summary> /// <typeparam name="TSource">The element type of <paramref name="source"/>.</typeparam> /// <typeparam name="TResult">The type of the result of this conversion.</typeparam> /// <param name="source">A source single result option.</param> /// <param name="ifZero"> /// A function to produce the result if <paramref name="source"/> represents a result of zero elements. /// </param> /// <param name="ifOne"> /// A function to produce the result if <paramref name="source"/> represents a result of one /// element, which accepts that element as a parameter. /// </param> /// <param name="ifMoreThanOne"> /// A function to produce the result if <paramref name="source"/> represents a result of more /// than one element. /// </param> /// <returns> /// The result of calling <paramref name="ifZero"/>, <paramref name="ifOne"/>, or <paramref /// name="ifMoreThanOne"/> if <paramref name="source"/> represents a result of zero, one, or /// more than one element, respectively. /// </returns> /// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception> /// <exception cref="InvalidOperationException"> /// <paramref name="ifZero"/> is <see langword="null"/> and <paramref name="source"/> /// represents a result of zero elements, or <paramref name="ifOne"/> is <see /// langword="null"/> and <paramref name="source"/> represents a result of one element, or /// <paramref name="ifMoreThanOne"/> is <see langword="null"/> and <paramref name="source"/> /// represents a result of more than one element. /// </exception> public static TResult Match <TSource, TResult>(this ISingleResultOpt <TSource> source, Func <TResult> ifZero = null, Func <TSource, TResult> ifOne = null, Func <TResult> ifMoreThanOne = null) { if (source == null) { throw new ArgumentNullException(nameof(source)); } return(source.ResolveSingleResultOption((isValidOption, hasValue, value) => { if (isValidOption) { if (hasValue) { if (ifOne == null) { throw Error.MatchCaseFailed(); } return ifOne(value); } else { if (ifZero == null) { throw Error.MatchCaseFailed(); } return ifZero(); } } else { if (ifMoreThanOne == null) { throw Error.MatchCaseFailed(); } return ifMoreThanOne(); } })); }
/// <summary> /// Converts a single result option to another option, substituting an empty option if this /// option represents more than one result. /// </summary> /// <typeparam name="TSource">The element type of <paramref name="source"/>.</typeparam> /// <param name="source">A source single result option.</param> /// <returns> /// An option equivalent to <paramref name="source"/>, if it represents a result of zero or /// one element; otherwise, an empty option. /// </returns> /// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception> public static IOpt <TSource> EmptyIfMoreThanOne <TSource>(this ISingleResultOpt <TSource> source) => source.ReplaceIfMoreThanOne(Opt.Empty <TSource>());
/// <summary> /// Converts a single result option to another option, substituting a full option containing /// the default value of the contained type if this option represents more than one result. /// </summary> /// <typeparam name="TSource">The element type of <paramref name="source"/>.</typeparam> /// <param name="source">A source single result option.</param> /// <returns> /// An option equivalent to <paramref name="source"/>, if it represents a result of zero or /// one element; otherwise, an option containing the default value of <typeparamref name="TSource"/>. /// </returns> /// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception> public static IOpt <TSource> DefaultIfMoreThanOne <TSource>(this ISingleResultOpt <TSource> source) => source.DefaultIfMoreThanOne(default(TSource));
/// <summary> /// Converts a single result option to another option, substituting a full option containing /// the specified default value if this option represents more than one result. /// </summary> /// <typeparam name="TSource">The element type of <paramref name="source"/>.</typeparam> /// <param name="source">A source single result option.</param> /// <param name="defaultValue"> /// The value to be contained by the returned option if <paramref name="source"/> represents /// more than one result. /// </param> /// <returns> /// An option equivalent to <paramref name="source"/>, if it represents a result of zero or /// one element; otherwise, an option containing <paramref name="defaultValue"/>. /// </returns> /// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception> public static IOpt <TSource> DefaultIfMoreThanOne <TSource>(this ISingleResultOpt <TSource> source, TSource defaultValue) => source.ReplaceIfMoreThanOne(Opt.Full <TSource>(defaultValue));
private static bool PlainOptEqualsSingleResultOpt(IOpt a, ISingleResultOpt b) => FixedEquals(a.ToFixedSingleResultOpt(), b.ToFixedSingleResultOpt());