Obsidian Phoenix
Obsidian Phoenix

Reputation: 4155

Specific Order on multiple items

I have a collection of actions that are either Enable or Disable, with a value to indicate true or false. Functionally, an Enable:True is equivalent to a Disable:False (the wo types exists for other legacy reasons).

I have a need to resolve a list of actions into a single relevant action, where an action resulting in a disable takes priority. i.e. If one action indicates that it should disable the target, and all other say it should enable them, then the disable wins.

I've come up with the code below:

void Main()
{
    var actions = GetActions();

    var x = actions.OrderBy(A => (A.ActionType == ActionType.Enable && A.Value)
                                || (A.ActionType == ActionType.Disable && !A.Value)).ToList();

    Console.WriteLine("Initial Order");
    x.Dump();

    x = x.Skip(1).ToList();

    actions.RemoveAll(A => x.Contains(A));

    Console.WriteLine("End Result");
    actions.Dump();
}

private List<Action> GetActions()
{
    var actions = new List<Action>();

    actions.Add(new Action() { ActionType = ActionType.Enable, Value = true });
    actions.Add(new Action() { ActionType = ActionType.Enable, Value = false });
    actions.Add(new Action() { ActionType = ActionType.Disable, Value = true });
    actions.Add(new Action() { ActionType = ActionType.Disable, Value = false });

    return actions;
}

// Define other methods and classes here
public class Action
{
    public ActionType ActionType { get; set; }
    public bool Value { get; set; }
}

public enum ActionType
{
    Enable,
    Disable
}

This gives me exactly what I want (i.e. a single record that indicates a disable action should take place). It also works no matter what values are set for the ActionType enum values (or even the Enum text).

The problem is, I don't understand why, and I'm concerned that something might cause it to not work.

Based on the order:

var x = actions.OrderBy(A => (A.ActionType == ActionType.Enable && A.Value)
                            || (A.ActionType == ActionType.ADisable && !A.Value)).ToList();

    // Order Is:
    // Enable  False
    // Disable True
    // Enable  True
    // Disable False

I would have expected that it would sort Enable:True and Disable:False at the top of the list, but it's actually putting them to the bottom of the list. Thats what I want, but why is it doing that?

Upvotes: 0

Views: 50

Answers (1)

Rapha&#235;l Althaus
Rapha&#235;l Althaus

Reputation: 60493

with your ordering

Enable + false => false

Disable + false => false

Enable + true => true

Disable + false => true

As false comes before true when ordering boolean values, the result is correct. Probably because 0 < 1 (well, at least that's the way it's implemented) ?

Just use OrderByDescending if you want true first (but that's not what you want).

But with your code, you won't be able to ensure the order between

Enable true

and

Disable false

for example.

Upvotes: 1

Related Questions