作为API合同的一部分,我对IList.RemoveAt的实现是否有任何限制?

时间:2016-07-06 16:39:57

标签: c# .net api-design

背景故事

我有一个包含项目列表的viewmodel。每个项目都有一个州;如果要从列表中删除以前存在的项目,它将保留在列表中,但会被标记为已删除,并且很明显,当用户单击“保存”时,它将被删除。

列表本身绑定到一个在IBindingList上运行的UI控件。当用户通过UI控件添加和删除行时,UI控件会调用IList.AddIList.RemoveAt

问题

由于我想保留预先存在的行并以不同方式标记它们,我有两个选择:

  1. IList.RemoveAt的实施可以简单地将项目标记为已删除并将其保留在列表中,并且无法引发ListChanged删除事件。这看起来最简单,最干净,但我想知道是否存在API期望实际删除了索引。想象一下像while (list.Count != 0) { Process(list[0]); list.RemoveAt(0); }这样的通用循环显然我必须避免这种情况,但是避免它的需要似乎是一种糟糕的耦合。我是否会对API犯罪?或者那段代码只是可以忽略的坏代码,因为它做了太多的假设?

  2. 我的实现可能允许删除发生并引发事件,然后将项目标记为已删除,重新插入项目并引发插入事件。这不会损害合同,因为可以理解列表可能会被多个组件变异,并且事件会使每个人保持同步。然而,它是额外的UI闪烁,感觉有点hacky。

  3. 我可以修改UI控件(它是第三方但可扩展),以便在列表中查找ISoftDelete接口。如果接口存在,则调用ISoftDelete.SetDeleted(int index, bool)而不是调用RemoveAt。这似乎相当干净,但它的额外复杂性不仅在列表API中,而且在每个UI控件中都需要了解此列表。这种分离是否值得花费?如果RemoveAt被调用会发生什么 - 该行将从视线中消失,这不是一个好的场景,所以它必须抛出异常或借用#2的解决方法。

  4. 修改

    奇怪!看看IList.RemoveAt(int index) with CONTRACTS_FULL - 它有以下内容:

        void IList.RemoveAt(int index)
        {
            //Contract.Requires(index >= 0);
            //Contract.Requires(index < ((IList)this).Count);
            //Contract.Ensures(((IList)this).Count == Contract.OldValue(((IList)this).Count) - 1);  // Not threadsafe
        }
    

    注意'not threadsafe'评论!这是否意味着如果可能的话,他们会取消注释该行?但基于索引的列表中的任何内容都不是线程安全的。

0 个答案:

没有答案