8

I'm trying to write a generic extension method that let's me do this:

this.startDate = startDateXAttribute.NullOrPropertyOf<DateTime>(() =>
{
    return DateTime.Parse(startDateXAttribute.Value);
});

NullOrPropertyOf() would return null if it's used on a null object (e.g. if startDateXAttribute was null), or return the result of a Func if it's not null.

What would this extension method look like?

dtb
  • 213,145
  • 36
  • 401
  • 431
SnickersAreMyFave
  • 5,047
  • 8
  • 26
  • 24

3 Answers3

26

There's no short form for that; implementing one is a fairly frequently requested feature. The syntax could be something like:

x = foo.?bar.?baz;

That is, x is null if foo or foo.bar are null, and the result of foo.bar.baz if none of them are null.

We considered it for C# 4 but it did not make it anywhere near the top of the priority list. We'll keep it in mind for hypothetical future versions of the language.

UPDATE: C# 6 will have this feature. See http://roslyn.codeplex.com/discussions/540883 for a discussion of the design considerations.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • 3
    hypothetical? I hope MS is not going to drop C# so soon ;) – vc 74 Sep 29 '10 at 06:58
  • 16
    @vc: I remind you all that Eric's musings about hypothetical features of unannounced future products that do not exist today and might never exist are *for entertainment purposes only* and do not constitute any promise to deliver any product with any feature at any time. – Eric Lippert Sep 29 '10 at 14:08
  • 4
    you're my definition for cautious – vc 74 Sep 29 '10 at 16:00
  • 2
    @Eric: Congratulations. You sound like a lawyer! – Matti Virkkunen Jun 06 '12 at 23:19
  • 1
    @EricLippert wouldn't `?.` be better? The first question mark style is more consistent with semantics of ternary operator (which is more like checking a condition), and then an ending period `.` opens the scope for intellisense to act and list all the existing members. My pick: `x = foo?.bar?.baz;` – nawfal Oct 15 '13 at 10:03
  • 2
    @nawfal: Excellent point. – Eric Lippert Oct 15 '13 at 14:36
  • @EricLippert Nemerle does the same! – nawfal Oct 19 '13 at 06:56
  • 1
    Update: On [Roslyn's list of language features](https://roslyn.codeplex.com/wikipage?title=Language%20Feature%20Status) this item is "planned". They seem to use `?.` and not `.?`. – Jeppe Stig Nielsen May 03 '14 at 06:43
  • The **"safe navigation operator"** `?.` (for example `var x = a?.b?.c?.d;`) is mentioned [here](http://blogs.msdn.com/b/jerrynixon/archive/2014/02/26/at-last-c-is-getting-sometimes-called-the-safe-navigation-operator.aspx) at MSDN, it received 3,752 votes at the user voice. Hopefully it will be implemented soon, since the equivalent `var x=(a==null)?null:((b==null)?null:((c==null)?null:a.b.c.d));` is just **UGLY.** – Matt Feb 13 '15 at 11:44
  • @Matt: C# 6 will have this feature. See http://roslyn.codeplex.com/discussions/540883 – Eric Lippert Feb 13 '15 at 16:50
1

The XAttribute Class provides an explicit conversion operator for this:

XAttribute startDateXAttribute = // ...

DateTime? result = (DateTime?)startDateXAttribute;

For the general case, the best option is probably this:

DateTime? result = (obj != null) ? (DateTime?)obj.DateTimeValue : null;
dtb
  • 213,145
  • 36
  • 401
  • 431
0

Is this what you're looking for? I think it breaks down if you pass a non-nullable value type, but it should work when you're using nullable types. Please let me know if there is something I've overlooked.

public static class Extension
{
    public static T NullOrPropertyOf<T>(this XAttribute attribute, Func<string, T> converter)
    {
        if (attribute == null)
        {
            return default(T);
        }
        return converter.Invoke(attribute.Value);
    }
}

class Program
{
    static void Main(string[] args)
    {
        Func<string, DateTime?> convertDT = (string str) =>
        {
            DateTime datetime;
            if (DateTime.TryParse(str, out datetime))
            {
                return datetime;
            }
            return null;
        };
        Func<string, string> convertStr = (string str) =>
        {
            return str;
        };
        XAttribute x = null;
        Console.WriteLine(x.NullOrPropertyOf<string>(convertStr));
        Console.WriteLine(x.NullOrPropertyOf<DateTime?>(convertDT));
        XName t = "testing";
        x = new XAttribute(t, "test");
        Console.WriteLine(x.NullOrPropertyOf<string>(convertStr));
        x = new XAttribute(t, DateTime.Now);
        Console.WriteLine(x.NullOrPropertyOf<DateTime?>(convertDT));
    }
}
nawfal
  • 70,104
  • 56
  • 326
  • 368
s_hewitt
  • 4,252
  • 24
  • 24