Skip to content

Instantly share code, notes, and snippets.

@trayburn
Created January 29, 2015 19:48
Show Gist options
  • Save trayburn/dbed51fc792e9e6eefc9 to your computer and use it in GitHub Desktop.
Save trayburn/dbed51fc792e9e6eefc9 to your computer and use it in GitHub Desktop.
Null Object Pattern helper extensions
public static class ObjectExtensions
{
/// <summary>
/// Null-safe member access helper.
/// Invokes the given accessor if the target object is not <c>null</c>.
/// </summary>
/// <typeparam name="T">
/// The type of the target object.
/// </typeparam>
/// <typeparam name="TResult">
/// The type of the return value of <paramref name="accessor"/>.
/// </typeparam>
/// <param name="target">
/// An object reference, or <c>null</c>.
/// </param>
/// <param name="accessor">
/// The delegate to be invoked if <paramref name="target"/> is not null.
/// </param>
/// <returns>
/// The result of invoking <paramref name="accessor"/> on <paramref name="target"/>,
/// if <paramref name="target"/> is not <c>null</c>;
/// otherwise, the default value of type <typeparamref name="TResult"/>.
/// </returns>
public static TResult _<T, TResult>(this T target, Func<T, TResult> accessor)
where T : class
{
return target == null ? default(TResult) : accessor(target);
}
/// <summary>
/// Null-safe member invocation helper.
/// Invokes the given action if the target object is not <c>null</c>.
/// </summary>
/// <typeparam name="T">
/// The type of the target object.
/// </typeparam>
/// <param name="target">
/// An object reference, or <c>null</c>.
/// </param>
/// <param name="action">
/// The delegate to be invoked if <paramref name="target"/> is not null.
/// </param>
public static void _<T>(this T target, Action<T> action)
where T : class
{
if (target != null) action(target);
}
public static TResult _<T, TResult>(this Func<T, TResult> func, T arg)
{
return func == null ? default(TResult) : func(arg);
}
public static Action<T> _<T>(this Action<T> action, T arg)
{
if (action != null)
action(arg);
return action;
}
public static T If<T>(this T target, bool condition, Func<T, T> @then)
{
return condition ? @then(target) : target;
}
public static TResult If<T, TResult>(this T target, bool condition, Func<T, TResult> @then, Func<T, TResult> @else)
{
return condition ? @then(target) : @else(target);
}
}
Because nulls are difficult:
c._(e => e.PossiblelyNullThing)._(e => e.PossibleOtherNull) ?? "Default Value"
Obviously, C# 6.0 will make this far more terse:
c?.PossiblelyNullThing?.PossibleOtherNull ?? "Default Value"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment