tags:

views:

193

answers:

6

I would like to get the two attribute-assignment lines below into one line since I'm going to build them into an application where they will be numerous.

Is there a way to express those two lines in one line of elegantly constructed C#, perhaps with a ?? operator like this?

string nnn = xml.Element("lastName").Attribute("display").Value ?? "";

Here's the code:

using System;
using System.Xml.Linq;

namespace TestNoAttribute
{
    class Program
    {
        static void Main(string[] args)
        {

            XElement xml = new XElement(
                new XElement("employee",
                    new XAttribute("id", "23"),
                    new XElement("firstName", new XAttribute("display", "true"), "Jim"),
                    new XElement("lastName", "Smith")));

            //is there any way to use ?? to combine this to one line?
            XAttribute attribute = xml.Element("lastName").Attribute("display");
            string lastNameDisplay = attribute == null ? "NONE" : attribute.Value;

            Console.WriteLine(xml);
            Console.WriteLine(lastNameDisplay);

            Console.ReadLine();

        }
    }
}
+3  A: 

Why not use a small helper function which takes an XElement and returns the lastNameDisplay string?

Readable code is far more valuable than compact code. +1 for being the only answer to sacrifice neither.
ojrac
+6  A: 

Sure, but it's awful, not elegant:

string lastNameDisplay = xml.Element("lastName").Attribute("display") == null ? "NONE" : xml.Element("lastName").Attribute("display").Value;

If you're willing, you could write an extension method:

public static string GetValue(this XAttribute attribute)
{
    if (attribute == null)
    {
        return null;
    }

    return attribute.Value;
}

Usage:

var value = attribute.GetValue();

HTH, Kent

Kent Boogaart
Extension method is the only way to do this.
Will
+1  A: 

Not exactly. What you're looking for is a null guard (I think that's what it's called), which c# does not have. It would only call the guarded property if the preceding object is not null.

Rex M
+3  A: 

You could do this:

string lastNameDisplay = (xml.Element("lastName").Attribute("display") ?? new XAttribute("display", "NONE")).Value;
Ben Lings
This is for the "null 'this' references in extension methods should throw NRE" crowd.
Will
This *does* answer the question, but I'm not sure I'd want to be creating extra objects when I don't have to.
lc
+2  A: 

Sure you can!

Just do this:

string lastNameDisplay = (string)xml.Element("lastName").Attribute("display") ?? "NONE";
Ryan Versaw
yes, that was what I was looking for, and still quite readable I think as long as you know what the ?? does, thanks!
Edward Tanguay
?? is before explicit casts in precedence?
Will
I was in a meeting or I would have replied earlier. The `XAttribute` will cast to a null string, which is then coalesced and replaced with "NONE".
Ryan Versaw
This is also very useful for other attribute types that may not exist (like a nullable int): `int demoInt = (int?)xml.Element("element").Attribute("attribute") ?? 12;`
Ryan Versaw
As someone voted this answer down, it would be great to be given an explanation for it - thanks!
Ryan Versaw
A: 

Not quite. The closest you'll get is with an extension method like the following:

public static string ValueOrDefault(this XAttribute attribute, string Default)
{
    if(attribute == null)
        return Default;
    else
        return attribute.Value;
}

Then you can shorten your two lines into:

string lastNameDisplay = xml.Element("lastName").Attribute("display").ValueOrDefault("NONE");
lc