Reputation:
I have a Request object which contains a list of Approvers. An approver has a name and an approval position.
Ultimately, a request will move through this chain, starting at Mathew and ended at John.
I need to be able to re-order these allowing adds and deletes as outlined below.
An approver can be -
Added at a certain position - ie. Add Peter at position 3 in which case the new order would be
Delete - ie. Delete Mark in which case the new order is
Edited - ie you can change John's position to 1 in which case the new order is
I have come up with a number of solutions, however none of them is particular elegant.
Any help would be much appreciated
Upvotes: 5
Views: 6331
Reputation: 1063864
Maintaining a position property is a pain, as you need to make lots of modifications to change something (while keeping everything logical). It also makes it hard to serialize/deserialize efficiently.
Can you not simply infer the position from the position in a List<T>
or similar? Then you can Add()
to the end, Insert()
to the middle and Remove()
from anywhere. To move something you simply Remove()
it and Insert()
it at the position you want?
Like so (formatted for space):
using System;
using System.Collections.ObjectModel;
using System.Linq;
// I only added this to use a lazier "collection initializer" below,
// which needs an Add(string) method...
class ApproverCollection : Collection<Approver> {
public void Add(string name) { Add(new Approver(name)); }
}
class Request {
public Request() { Approvers = new ApproverCollection(); }
public ApproverCollection Approvers { get; private set; }
}
class Approver {
public Approver(string name) { Name = name; }
public string Name { get; set; }
}
static class Program {
static void Main() {
Request req = new Request {
Approvers = {"Mathew", "Mark", "Luke", "John"}
};
req.ShowState("Initial");
req.Approvers.Insert(2, new Approver("Peter"));
req.ShowState("Inserted Peter");
Approver mark = req.Approvers.Single(x => x.Name == "Mark");
req.Approvers.Remove(mark);
req.ShowState("Removed Mark");
Approver john = req.Approvers.Single(x => x.Name == "John");
req.Approvers.Remove(john);
req.Approvers.Insert(0, john);
req.ShowState("Moved John");
}
static void ShowState(this Request request, string caption) {
Console.WriteLine();
Console.WriteLine(caption);
int pos = 1;
foreach(Approver a in request.Approvers) {
Console.WriteLine("{0}: {1}", pos++, a.Name);
}
}
}
Upvotes: 4
Reputation: 1503090
How large are the lists likely to be? List<T>
is likely to be the easiest representation of the collection, but it means a copy is required every time you insert into or remove from the middle of the list. "Editing" the list basically means a remove/insert.
Iteration is then straightforward.
An alternative might be LinkedList<T>
- which makes iteration simple and "insert after", "insert before" and "delete" cheap if you hang onto the LinkedListNode<T>
associated with each of your approvers. But it doesn't make it easy to say "this reviewer should now be at position 3" - you'd have to iterate through to find position 3 first (or 2, anyway). If it's a case of "move this approver after this one" then it's ideal.
Upvotes: 5