117

I've got a linq query that I want to order by f.bar, which is a string, but I also want to order it by f.foo, which is a boolean field, first. Like the query below.

(from f in foo
orderby f.foo, f.bar
select f)

Although this compiles it doesn't work as expected. It just orders by f.bar ignoring the boolean field.

I'm being daft I know, but what do I need to do to get this behaviour?

Thanks

mat-mcloughlin
  • 5,944
  • 11
  • 40
  • 58

4 Answers4

189

That should work fine - it should order the entities with a false foo value first, then those with a true foo value.

That certainly works in LINQ to Objects - which LINQ provider are you actually using?

Here's a LINQ to Objects example which does work:

using System;
using System.Linq;

public static class Test
{
    public static void Main()
    {
        var data = new[]
        {
            new { x = false, y = "hello" },
            new { x = true, y = "abc" },
            new { x = false, y = "def" },
            new { x = true, y = "world" }
        };

        var query = from d in data
                    orderby d.x, d.y
                    select d;

        foreach (var result in query)
        {
            Console.WriteLine(result);
        }
    }

}
Jon Skeet
  • 1,261,211
  • 792
  • 8,724
  • 8,929
129

Just wanted to do this and it seems like something with no implicit ordering. I did the following to be more explicit:

Something.OrderBy(e=>e.SomeFlag ? 0 : 1) 

to sort something true to false.

JonnyRaa
  • 6,268
  • 5
  • 39
  • 43
  • 28
    I sort of like this more than the built in way. Mainly because even if there is an implied ordering for true/false, it isn't really obvious to anyone who hasn't done it before. So someone that doesn't know looking at code in the future could think it sorts true to false, when really it sorts false to true... at least with this solution, the code makes it painfully obvious which way you intend to sort. – Robert Noack Jul 29 '13 at 20:24
  • 2
    yeah I like that in code! If you have to go onto msdn or stackoverflow to read documentation to understand code then it isnt great code in my opinion – JonnyRaa Aug 13 '13 at 14:39
  • 2
    Smells like magic numbers to me. Am I wrong in assuming that every programmer should inherently know very well that a boolean `true` means `a single bit set to 1`? To me, the truth of `true > false` is about as obvious as can be. – Mels Feb 21 '14 at 11:03
  • 1
    However, I do see how `.OrderBy(e=>e.SomeFlag)` could lead to some confusion, as `SomeFlag` would be assumed to be a numeric type (as is the case with most sorts we see "in the wild"). Perhaps `.OrderBy(e => e.SomeFlag == true)` would help to avoid that confusion. It sure would perform better than branching into ints, AFAIK. – Mels Feb 21 '14 at 11:07
  • 4
    @Mels not magic numbers. Explicit values used for sorting and sorting only. The values could be 42 and 69, the point is the reader of the code knows that one of them is smaller, therefore will be first. The reader of the code probably does not know which way an OrderBy will put the bools - will true be first, or will false be first. `true > false` is not universally known, whereas `1 > 0` is. – Dan F Apr 02 '14 at 04:12
  • 1
    @Mels in VB6 `true` has a value of -1: http://stackoverflow.com/questions/4275800/what-are-the-integer-values-of-boolean-false-and-true-in-vb6 Any non-zero value can be considered `true`. – Lukazoid Oct 23 '15 at 12:01
  • 9
    Note that `.OrderBy(e => e.SomeFlag == true)` would be equivalent to `.OrderBy(e => e.SomeFlag)` whereas `.OrderBy(e => e.SomeFlag ? 0 : 1)` is the equivalent of `.OrderByDescending(e => e.SomeFlag)`. The first two sorts false before true, the other two sorts true before false. – EriF89 May 13 '16 at 15:34
  • I'd like to reiterate what @EriF89 said. Jonny, can you please update your answer to switch the 0 and 1 or state that it sorts from false to true. – Steve Aug 31 '16 at 15:17
  • 1
    @Steve What EriF89 says is true but I think you've misinterpreted it. It highlights the issue treating bools as numbers (it can be confusing!). The logic in my answer is 'if some flag == true return 0 else return 1' so it does sort true to false with an ascending sort – JonnyRaa Sep 26 '16 at 12:24
  • How about adding comment? Something.OrderBy(e=>e.SomeFlag) // orders false before true. But see my answer also for a BooleanComparer.. – Wouter Sep 03 '18 at 11:30
1

In order to be more explicit about the order being used.

Something.OrderBy(e => e.SomeFlag, new BooleanComparer());

public class BooleanComparer : IComparer<bool>
{
    public int Compare(bool x, bool y)
    {
        int p = x ? 1 : 0;
        int q = y ? 1 : 0;
        return p - q; 
    }
}
Wouter
  • 1,649
  • 13
  • 24
0

Please try following code if you get list orderby true .

db.member.where(x=>x.id==memberId).OrderBy(x=>!x.IsPrimary?1:0).ToList();