views:

246

answers:

4

In functional languages there is often a Maybe monad which allows you to chain multiple calls on an object and have the entire expression return None/null if any part of the chain evaluates to nothing, rather than the typical NullReferenceException you'd get in C# by chaining calls where one object could be null.

This can be trivially implemented by writing a Maybe<T> with some extension methods to allow similar behaviour in C# using query comprehensions, which can be useful when processing XML with optional elements/attributes e.g.

var val = from foo in doc.Elements("foo").FirstOrDefault().ToMaybe()
          from bar in foo.Attribute("bar").ToMaybe()
          select bar.Value;

But this syntax is a bit clunky and unintuitive as people are used to dealing with sequences in Linq rather than single elements, and it leaves you with a Maybe<T> rather than a T at the end. Would a conditional de-reference operator (e.g. ..) be sufficiently useful to make it into the language? e.g.

var val = doc.Elements("foo").FirstOrDefault()..Attribute("bar")..Value;

The conditional de-reference would expand to something like:

object val;
var foo = doc.Elements("foo").FirstOrDefault();
if (foo != null)
{
    var bar = foo.Attribute("bar");
    if (bar != null)
    {
        val = bar.Value;
    }
    else
    {
        val = null;
    }
}

I can see that this could potentially lead to terrible abuse like using .. everywhere to avoid a NullReferenceException, but on the other hand when used properly it could be very handy in quite a few situations. Thoughts?

+1  A: 

Chaining multiple calls on an object makes me fear violations of the Law of Demeter. Thus, I am skeptical that this feature is a good idea, at least in terms of solving the specific problem you are using as an example.

Brian
I specifically chose the XML example so as to show a situation where it's virtually impossible *not* to violate this law while doing anything actually useful, as XML is a well-documented tree structure where I don't feel this law really applies.
Greg Beech
The problem with the Law of Demeter is that someone named it "Law of Demeter" rather than "Guideline of Demeter" which is what it is. Guidelines are there to guide us, but they shouldn't stand in the way of a good idea.
Jeff Yates
I'd reply that this is what xpath is for but I can see where a pure string would be considered uglier by some. That said, most of the time this is NOT something you want to do.
Brian
@Brian - Yes, this can be what XPath is for. But it's also what Linq to XML is for.
Greg Beech
A: 

It's an interesting idea that could be achieved with an extension method. Something like this, for example (note, just for example - I'm sure it can be refined):

public static IEnumerable<T> Maybe<T>(this IEnumerable<T> lhs, Func<IEnumerable<T>, T> rhs)
{
  if (lhs != null)
  {
    return rhs(lhs);
  }

  return lhs;
}
Jeff Yates
A: 

I suspect a combination of NUllable and extension methods would allow a significant portion of this to b achieved.

This would limit T to value types of course.

(TBH I would rather see tuple support in the langauge and eliminate out parameters, as F# does.)

You code can be simplified, set val to null and you eliminate else branches.

Richard
A: 

I can see the potential usefulness, but other than a slight performance impact if the elements are often null, why not just surround the code block with a try..catch block for a NullReferenceException instead?

Eric Petroelje
The issue with using a try/catch is that it throws you out of the query. With an operation that copes with null, the query can complete and give a valid result, which could be very useful if you have various expressions in your query.
Jeff Yates
Exceptions for flow control is virtually never a good idea... I won't go into why here; there's a lot of information on this site and the internet in general about this.
Greg Beech
Ahh, I was under the impression that no valid result would be arrived at if one of the query parts returned null - it just wouldn't generate an error. As for using Exceptions for flow control, I agree - which is why I mentioned the elements not often being null.
Eric Petroelje