utilizo algo como esto en mis proyectos:
public interface IOptional<T> : IEnumerable<T> { }
public interface IMandatory<T> : IEnumerable<T> { }
Dos interfaz derivada de IEnumerable para la compatibilidad con LINQ
public class Some<T> : IOptional<T>
{
private readonly IEnumerable<T> _element;
public Some(T element)
: this(new T[1] { element })
{
}
public Some()
: this(new T[0])
{}
private Some(T[] element)
{
_element = element;
}
public IEnumerator<T> GetEnumerator()
{
return _element.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public class Just<T> : IMandatory<T>
{
private readonly T _element;
public Just(T element)
{
_element = element;
}
public IEnumerator<T> GetEnumerator()
{
yield return _element;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Implementación de clases justas y algún aviso
: La implementación de estas clases es muy similar, pero tiene una diferencia. Class Just deriva de la interfaz IMandatory y solo tiene un constructor, lo que garantiza que la instancia de la clase siempre tenga un valor dentro.
public static class LinqExtensions
{
public static IMandatory<TOutput> Match<TInput, TOutput>(
this IEnumerable<TInput> maybe,
Func<TInput, TOutput> some, Func<TOutput> nothing)
{
if (maybe.Any())
{
return new Just<TOutput>(
some(
maybe.First()
)
);
}
else
{
return new Just<TOutput>(
nothing()
);
}
}
public static T Fold<T>(this IMandatory<T> maybe)
{
return maybe.First();
}
}
Algunas extensiones de practicidad
Aviso: Método de extensión de ajuste requieren dos funciones y IMandatory regresan, después de esto, utilizar el método de extensión Fold .First() sin ninguna verificación.
Ahora podemos utilizar toda la potencia de LINQ y escribir código similar este (me refiero a las mónadas .SelectMany())
var five = new Just<int>(5);
var @null = new Some<int>();
Console.WriteLine(
five
.SelectMany(f => @null.Select(n => f * n))
.Match(
some: r => $"Result: {r}",
nothing:() => "Ups"
)
.Fold()
);
Esto podría ser útil: http://stackoverflow.com/questions/ 2522928/how-can-i-implement-the-null-object-design-pattern-in-a-generic-form – Maarten