-1

I have an old compiler server (VS 2010), which, obviously, can't compile such instructions:

var result = a?.b()?.c?.d;

Is there alternative I can use? Is it possible to do this through expression tree? For example, like this:

var result = NullSafe(()=> a.b().c.d);
eocron
  • 6,885
  • 1
  • 21
  • 50
  • Create an extension method – Nkosi Feb 02 '17 at 15:14
  • 2
    @Nkosi it's not *that* simple. People did create such extension methods back then, that received expressions. It needed a bit of work to get everything straight and cover edge cases – Panagiotis Kanavos Feb 02 '17 at 15:15
  • Kind of? Some examples will help me understand how I should 'Create' it. – eocron Feb 02 '17 at 15:15
  • Worth noting that if you have a block of code that's going through that many properties/methods in one chain, you might want to consider refactoring it anyway. See the [Law of Demeter](https://en.wikipedia.org/wiki/Law_of_Demeter). – James Thorpe Feb 02 '17 at 15:23
  • Null-safe operator result depend on result of previous one. Law of Demeter is succeded. – eocron Feb 02 '17 at 15:28

1 Answers1

3

There were quite a few attempts to do this before it became a language feature. It's a bit hard to find the references now, but you can get an idea how it can be done and why it's not that easy.

This snippet for example looks simple:

public static R NullSafe<T, R>(this T obj, Func<T, R> f) where T : class
{
       return obj != null ? f(obj) : default(R);
}

You can use it almost like an operator:

deliveryCode = order.NullSafe(o => o.DeliveryCompany).NullSafe(dc => dc.FileArtworkCode);

But it doesn't work with value types. This older snippet uses EqualityComparer :

public static TOut NullSafe<TIn, TOut>(this TIn obj, Func<TIn, TOut> memberAction)
{
    //Note we should not use obj != null because it can not test value types and also
    //compiler has to lift the type to a nullable type for doing the comparision with null.
    return (EqualityComparer<TIn>.Default.Equals(obj, default(TIn))) 
                         ? memberAction(obj) 
                         : default(TOut);
}

It will take a bit of digging to find more complete examples. I remember trying methods similar to these way back when until I found a more complete one.

This SO answer to a similar question does away with chaining and allows one to write:

foo.PropagateNulls(x => x.ExtensionMethod().Property.Field.Method());

The implementation is a bit involved though, to say the least.

Community
  • 1
  • 1
Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
  • Although, I tried to avoid using a bunch of lambdas for this...Well, thx, good example indeed =) – eocron Feb 02 '17 at 15:26
  • Check [this SO question then](http://stackoverflow.com/questions/123088/possible-pitfalls-of-using-this-extension-method-based-shorthand). The second answer does away with chaining but OMG - kind of tricky implementation. And then, as the commenters say, there is LINQ – Panagiotis Kanavos Feb 02 '17 at 15:28
  • 1
    @eocron I think I ended up with something similar back then but I can't find the source now. It was a blog post, not an SO question and *maybe* it cached reflection types to speed up execution. You get an idea why that's not so easy after all – Panagiotis Kanavos Feb 02 '17 at 15:34
  • I though about doing something similar myself, but tried to ask first if it is already have been made. I think I can adjust that example to my needs. Thank you a lot =) – eocron Feb 02 '17 at 15:38
  • Why not upgrade? VS Community is free and essentially the same as VS Pro. You can use it to target all runtimes. And the earliest supported .NET version is .NET 4.5.2 which can't be targeted by 2010. Yes, if you have an OS that came out with 3.5 you get support for that through the OS but that's a very special case. 4.0 is definitelly unsupported – Panagiotis Kanavos Feb 02 '17 at 15:43