3

I have an Xelement containing a number of elements.

I have the following code to sort them:

var calculation = from y in x.Elements("row")
                 orderby y.Element("BUILD_ORDER").Value
                 select new
                 {
                     calcAttribute = y.Element("ELEMENT").Value

                 };

Which works fine, until BUILD_ORDER > 10, it orders 10 just after 1.

If I want it in strict numerical order, I case the element to an Int, is this the correct way to do it, or does LINQ have an inbuilt extension/method?

orderby Convert.ToInt32(y.Element("BUILD_ORDER").Value)
Justin Morgan - On strike
  • 30,035
  • 12
  • 80
  • 104
Darren Young
  • 10,972
  • 36
  • 91
  • 150

4 Answers4

7

LINQ to Objects doesn't have the built in conversion, but LINQ to XML does:

var calculation = from y in x.Elements("row")
                  orderby (int) y.Element("BUILD_ORDER")
                  select new
                  {
                      calcAttribute = y.Element("ELEMENT").Value
                  };

Is there any reason why you're using an anonymous type though, rather than just selecting the value you want? For example:

var calculation = from y in x.Elements("row")
                  orderby (int) y.Element("BUILD_ORDER")
                  select y.Element("ELEMENT").Value;

Note that both of these will throw an exception if the BUILD_ORDER or ELEMENT subelements are missing. You can fix that using a conversion to int? instead of int for BUILD_ORDER, and a conversion to string for ELEMENT:

var calculation = from y in x.Elements("row")
                  orderby (int?) y.Element("BUILD_ORDER")
                  select (string) y.Element("ELEMENT");

This will still fail if BUILD_ORDER exists but can't be parsed as an integer of course.

If your data should always have these elements, the first form is better, as it'll detect any data errors earlier.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 2
    Just as a clarification this is because XElement has an operator overload for Explict Casting to type int as well as many other [XElement Operators](http://msdn.microsoft.com/en-us/library/system.xml.linq.xelement.op_explicit(v=VS.90).aspx) – jbtule Mar 01 '11 at 16:38
  • Why didn't I think of using the XElement's explicit casting behavior? This sort of thing is why I don't mind getting Skeeted. :) – Justin Morgan - On strike Mar 01 '11 at 17:34
  • Thanks Jon, the reason I am using the anonymous type is that my original code had a number of values being extracted that I needed to use. I haven't changed the code yet. As far as the errors are concerned - I have learned that multiple times today :) I had never heard of (int?) before, I'll have a read up on that. Thanks for the great answer. – Darren Young Mar 01 '11 at 17:45
  • @Jon, Google doesn't seem to be liking (int?), would you mind explaining how it work please? – Darren Young Mar 01 '11 at 17:49
  • 1
    @Darren: It's syntactic sugar for `Nullable`. Look up nullable value types in your favourite C# book or web page. – Jon Skeet Mar 01 '11 at 17:56
2

Looks good to me. You could also use Int32.Parse(...). I'm not aware of any built-in method for sorting strings as integers, but you certainly could write your own.

Eric Mickelsen
  • 10,309
  • 2
  • 30
  • 41
2

Yes, since your XML values are not typed, you have to cast them manually for .NET to be able to sort numerically.

By the way, int.Parse will give you slightly better performance.

madd0
  • 9,053
  • 3
  • 35
  • 62
2

Looks like it's reading the build order as a string instead of an int. Your sample should work, or try

orderby int.Parse(y.Element("BUILD_ORDER").Value)
Justin Morgan - On strike
  • 30,035
  • 12
  • 80
  • 104