linq сортировка списка по булевым полям

Имеется тестовый класс:

public class TestData
{
    public bool IsImportant { get; set; }
    public bool IsImportant1 { get; set; }
    public bool IsImportant2 { get; set; }
    public string Data { get; set; }
}

P.S заранее прошу не придираться к неймингу )

Я создаю список объектов TestData , и мне нужно сортировать по полям IsImportant или IsImportant1 или IsImportant2

 // Add data to the list.
var items = new List<TestData>();
items.Add(new TestData() { IsImportant = true, Data = "Bird" });
items.Add(new TestData() { IsImportant1 = true, Data = "Cat" });
items.Add(new TestData() { IsImportant2 = true, Data = "Human" });

// Sort by bool on class.
var sorted = items.OrderBy(x => x.IsImportant1).ToArray();

// Put "important" items first.
foreach (var item in sorted)
{
    Console.WriteLine( $"{ item.Data} ; {item.IsImportant}; {item.IsImportant1}; { item.IsImportant2}");
}

Результат вывода :

Bird ; True; False; False
Human ; False; False; True
Cat ; False; True; False

Вопрос , почему не сортирует по полю IsImportant1? По идее первым должен быть Cat ? Как сделать так чтобы первым в списке выводился Cat. Просто у меня есть метод который будет в зависимости от параметра сортировать по определенному полю список объектов и выводить его.


Ответы (1 шт):

Автор решения: Max S

Интерфейс IComparable<T> для булевого типа реализован так, что значение False меньше (дословно – "в порядке сортировки находится до") True. Исходный код структуры Boolean:

public int CompareTo(Boolean value) {
    if (m_value==value) {
        return 0;
    } else if (m_value==false) {
        return -1;
    }
    return 1;    
}

Поэтому в вашем примере Cat идет последним – значение его свойства IsImportant1, по которому вы проводите сортировку, равно True.

Если вам нужно изменить поведение на противоположное – можно вместо

var sorted = items.OrderBy(x => x.IsImportant1).ToArray();

написать:

var sorted = items.OrderByDescending(x => x.IsImportant1).ToArray();

Также, можете раскрыть выборку ключа сортировки более явно для себя, например так:

items.OrderBy(x => x.IsImportant1 == false ? 0 : 1); // False будут идти раньше True
items.OrderBy(x => x.IsImportant1 == true ? 0 : 1); // True будут идти раньше False
→ Ссылка