io uso qualcosa di simile nei miei progetti:
public interface IOptional<T> : IEnumerable<T> { }
public interface IMandatory<T> : IEnumerable<T> { }
Due un'interfaccia derivata dalla IEnumerable per la compatibilità 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();
}
}
Attuazione delle classi soli e un po '
Avviso: L'implementazione di queste classi è molto simile, ma ha una differenza. Classe Derivata dall'interfaccia IMandatory e ha un solo costruttore, che garantisce quell'istanza di classe Ha sempre un valore all'interno.
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();
}
}
Alcune estensioni per praticità
Avviso: Metodo di estensione Partita necessari due funzioni e ritornano IMandatory, dopo questo, metodo di estensione Fold utilizzare .Prima() senza alcun controllo.
Ora possiamo usare tutta la potenza di LINQ e scrivere codice simile questa (intendo monadi .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()
);
Questo potrebbe essere utile: http://stackoverflow.com/questions/ 2522928/how-can-i-implement-the-null-object-design-pattern-in-a-generic-form – Maarten