tôi sử dụng một cái gì đó như thế này trong các dự án của tôi:
public interface IOptional<T> : IEnumerable<T> { }
public interface IMandatory<T> : IEnumerable<T> { }
Hai giao diện bắt nguồn từ IEnumerable để tương thích với 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();
}
}
Thực hiện các lớp học Chỉ và một số báo
: Việc thực hiện các lớp này rất giống nhau, nhưng nó có một sự khác biệt. Lớp Chỉ xuất phát từ giao diện IMandatory và chỉ có một hàm tạo, đảm bảo rằng cá thể của lớp Chỉ cần luôn có một giá trị bên trong.
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();
}
}
Một số phần mở rộng cho thực tiễn
Chú ý: Phương pháp mở rộng trận đấu đòi hỏi hai chức năng và trở IMandatory, sau này, phương pháp khuyến nông Fold sử dụng .First() mà không cần bất kỳ kiểm tra.
Bây giờ chúng ta có thể sử dụng đầy đủ sức mạnh của LINQ và viết mã tương tự này (Ý tôi là monads .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()
);
Điều này có thể hữu ích: http://stackoverflow.com/questions/ 2522928/how-can-i-implement-the-null-object-design-pattern-in-a-generic-form – Maarten