Created
October 18, 2011 11:25
-
-
Save ThatRendle/1295201 to your computer and use it in GitHub Desktop.
Maybe Monad in C#
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace MaybeMonad | |
{ | |
using System; | |
using System.Collections.Generic; | |
using System.Linq.Expressions; | |
using System.Reflection; | |
static class Monads | |
{ | |
/// <summary> | |
/// Returns the value of an expression, or <c>default(T)</c> if any parts of the expression are <c>null</c>. | |
/// </summary> | |
/// <typeparam name="T">The type of the Expression</typeparam> | |
/// <param name="expression">A parameterless lambda representing the path to the value.</param> | |
/// <returns>The value of the expression, or <c>default(T)</c> if any parts of the expression are <c>null</c>.</returns> | |
public static T Maybe<T>(Expression<Func<T>> expression) | |
{ | |
var value = Maybe(expression.Body); | |
if (value == null) return default(T); | |
return (T)value; | |
} | |
static object Maybe(Expression expression) | |
{ | |
var constantExpression = expression as ConstantExpression; | |
if (constantExpression != null) | |
{ | |
return constantExpression.Value; | |
} | |
var memberExpression = expression as MemberExpression; | |
if (memberExpression != null) | |
{ | |
var memberValue = Maybe(memberExpression.Expression); | |
if (memberValue != null) | |
{ | |
var member = memberExpression.Member; | |
return GetValue(member, memberValue); | |
} | |
} | |
return null; | |
} | |
private static object GetValue(MemberInfo member, object memberValue) | |
{ | |
var propertyInfo = member as PropertyInfo; | |
if (propertyInfo != null) return propertyInfo.GetValue(memberValue, null); | |
var fieldInfo = member as FieldInfo; | |
if (fieldInfo != null) return fieldInfo.GetValue(memberValue); | |
return null; | |
} | |
} | |
internal class Program | |
{ | |
private static void Main(string[] args) | |
{ | |
foreach (var person in TestCases()) | |
{ | |
var postCode = Monads.Maybe(() => person.Address.PostCode); | |
Console.WriteLine(postCode ?? "NULL"); | |
} | |
} | |
private static IEnumerable<Person> TestCases() | |
{ | |
yield return null; | |
yield return new Person {Name = "Bob"}; | |
yield return new Person {Name = "Bob", Address = new Address()}; | |
yield return new Person {Name = "Bob", Address = new Address {PostCode = "SL4 1QP"}}; | |
} | |
} | |
class Person | |
{ | |
public string Name { get; set; } | |
public Address Address { get; set; } | |
} | |
class Address | |
{ | |
public string PostCode { get; set; } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment