具有隐式排序顺序的 IList
我想创建一个 IList
,它始终以默认/隐式排序顺序维护其 Child
对象(即,无论对底层进行添加/删除)列表)。
我特别想要避免的是,所述 IList
的所有使用者每次想要时都需要显式调用 IEnumerable
列举一下。除了违反 DRY 之外,这种方法还会破坏封装,因为消费者必须知道我的列表甚至已排序,这实际上与他们无关:)
看起来最合乎逻辑/最有效的解决方案是公开 IList< Child>
作为 IEnumerable
(以防止 List 突变)并向包含的 Parent
添加显式添加/删除方法。这样,我可以拦截需要重新排序的列表更改,并通过 Linq 应用更改:
public class Child {
public string StringProperty;
public int IntProperty;
}
public class Parent{
private IList<Child> _children = new List<Child>();
public IEnumerable<Child> Children{
get
{
return _children;
}
}
private void ReSortChildren(){
_children = new List<Child>(child.OrderBy(c=>c.StringProperty));
}
public void AddChild(Child c){
_children.Add();
ReSortChildren()
}
public void RemoveChild(Child c){
_children.Remove(c);
ReSortChildren()
}
}
不过,这种方法不会拦截对底层 Child.StringProperty
所做的更改(在本例中case 是驱动排序的属性)。对于这样一个基本问题一定有一个更优雅的解决方案,但我还没有找到。
编辑: 我不清楚我是否更喜欢 LINQ 兼容的解决方案。我宁愿不诉诸使用 .NET 2.0 构造(即 SortedList)
I'd like to create an IList<Child>
that maintains its Child
objects in a default/implicit sort order at all times (i.e. regardless of additions/removals to the underlying list).
What I'm specifically trying to avoid is the need for all consumers of said IList<Child>
to explicitly invoke IEnumerable<T>.OrderBy()
every time they want to enumerate it. Apart from violating DRY, such an approach would also break encapsulation as consumers would have to know that my list is even sorted, which is really none of their business :)
The solution that seemed most logical/efficient was to expose IList<Child>
as IEnumerable<Child>
(to prevent List mutations) and add explicit Add/Remove methods to the containing Parent
. This way, I can intercept changes to the List that necessitate a re-sort, and apply one via Linq:
public class Child {
public string StringProperty;
public int IntProperty;
}
public class Parent{
private IList<Child> _children = new List<Child>();
public IEnumerable<Child> Children{
get
{
return _children;
}
}
private void ReSortChildren(){
_children = new List<Child>(child.OrderBy(c=>c.StringProperty));
}
public void AddChild(Child c){
_children.Add();
ReSortChildren()
}
public void RemoveChild(Child c){
_children.Remove(c);
ReSortChildren()
}
}
Still, this approach doesn't intercept changes made to the underlying Child.StringProperty
(which in this case is the property driving the sort). There must be a more elegant solution to such a basic problem, but I haven't been able to find one.
EDIT:
I wasn't clear in that I would preferable a LINQ compatible solution. I'd rather not resort to using .NET 2.0 constructs (i.e. SortedList)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
使用
SortedList
怎么样?What about using a
SortedList<>
?您可以采取的一种方法是让
Child
发布一个OnStringPropertyChanged
事件,该事件传递StringProperty
的先前值。然后创建SortedList
的派生,它重写Add
方法以将处理程序连接到该事件。每当事件触发时,从列表中删除该项目并使用 StringProperty 的新值重新添加它。如果您无法更改Child
,那么我将创建一个派生自或包装Child
的代理类来实现该事件。如果您不想这样做,我仍然会使用
SortedList
,但在需要更改StringProperty
时在内部管理上述排序逻辑。为了做到 DRY,最好通过正确管理排序的通用方法将所有更新路由到 StringProperty,而不是直接从类中的各个位置访问列表并重复排序管理逻辑。我还要警告不要允许控制器传入对
Child
的引用,这允许他在将StringProperty
添加到列表后对其进行操作。One way you could go about it is to have
Child
publish an eventOnStringPropertyChanged
which passes along the previous value ofStringProperty
. Then create a derivation ofSortedList
that overrides theAdd
method to hookup a handler to that event. Whenever the event fires, remove the item from the list and re-add it with the new value of StringProperty. If you can't changeChild
, then I would make a proxy class that either derives from or wrapsChild
to implement the event.If you don't want to do that, I would still use a
SortedList
, but internally manage the above sorting logic anytime theStringProperty
needs to be changed. To be DRY, it's preferable to route all updates toStringProperty
through a common method that correctly manages the sorting, rather than accessing the list directly from various places within the class and duplicating the sort management logic.I would also caution against allowing the controller to pass in a reference to
Child
, which allows him to manipulateStringProperty
after it's added to the list.我认为如果您从 KeyedCollection,你会得到你需要的。但这只是基于阅读文档。
编辑:
如果这有效,那么不幸的是,这并不容易。这个家伙中的底层查找字典和底层列表都没有排序,它们也没有足够暴露以便您能够替换它们。但是,它可能会提供一种模式供您在自己的实现中遵循。
I think that if you derive from KeyedCollection, you'll get what you need. That is only based on reading the documentation, though.
EDIT:
If this works, it won't be easy, unfortunately. Neither the underlying lookup dictionary nor the underlying List in this guy is sorted, nor are they exposed enough such that you'd be able to replace them. It might, however, provide a pattern for you to follow in your own implementation.