views:

45

answers:

3

Hi,

I was asked whats wrong/how can the following scenario can be fixed

Customer customer = null;
customer.WhenNull(c => new Customer())
        .Foo();

// instead of
Customer customer = null;
if (customer == null)
{
   customer = new Customer();
}
customer.Foo();

One developer sends me his Version of the WhenNull extension

public static T WhenNull<T>(this T source, Action<T> nullAction)
{
   if (source != null)
   {
      return source;
   } 

   if (nullAction == null)
   {
       throw new ArgumentNullException("nullAction");
   }

   nullAction(source);

   return source;
}

His problem / intention is, that he doesn't want to specify the underlying object in the lambda expression (in this case "customer")

Customer customer = null;
customer.WhenNull(c => customer = new Customer())
        .Foo();

I thought this can't be done.
Is this correct?

+7  A: 

You could do:

static T WhenNull<T>(this T t) where T : class, new()
{
  return t ?? new T();
}

Also noted: You want to use Func<T> not Action<T> as per your example code.

Edit 2:

You probably want this:

static T WhenNull<T>(this T t, Func<T> init) where T : class
{
  if (t == null)
  {
    t = init();  // could return here, but for debugging this is easier
  }
  return t;
}

Usage:

something.WhenNull(() => new Something()).Foo()
leppie
+1 for adding a `class` constraint. However, the `new()` constraint shouldn't be necessary in the 2nd variant.
Lucero
+2  A: 

If you really want shorthand syntax, you could just do:

(customer = customer ?? new Customer()).Foo();

Wouldn't recommend it though.

Ani
alternatively (customer ?? (customer = new Customer()).Foo()
veggerby
A: 

You could use Func<T> instead:

public static T WhenNull<T>(this T source, Func<T> nullFunc)
{
   if (source != null)
   {
      return source;
   } 

   if (nullFunc == null)
   {
       throw new ArgumentNullException("nullFunc");
   }

   return nullFunc();
}

Or as leppie states use the coalescing operator and the new() contraint if you do not want to specify the lamba.

veggerby
Not could, but should! :)
leppie
@leppie true :)
veggerby