c#代码契约——如何确保项目集合包含具有唯一属性的项目
本文关键字:项目 包含具 集合 唯一 属性 确保 契约 代码 何确保 | 更新日期: 2023-09-27 18:17:48
基本上,我有以下内容:
public class MyClass
{
public MyClass(ICollection<MyObject> coll)
{
Contract.Requires(coll != null);
Contract.Requires(Contract.ForAll(coll, obj => obj != null));
Contract.Requires(Contract.ForAll(coll, obj => (????)); //What goes here?
}
}
public class MyObject
{
public object PropA { get; set; }
public object PropB { get; set; }
}
要求如下:
- 集合中的所有PropA项目都是唯一的(没有重复)
- 集合中的所有PropB项目都是唯一的(没有重复)
我似乎不知道该怎么处理我的Contract.ForAll(...)
语句。
奖励:如果我可以组合Contract.ForAll(...)
语句而不破坏代码契约?
我可能在这里完全错了,从来没有使用过契约,但假设Contract.Requires
可以传递任意的bool
,你不能这样做:
Contract.Requires(coll.GroupBy(o => o.PropA).Count() == coll.Count);
, PropB
?
我相信下面的方法可以达到这个效果:
Contract.Requires(
Contract.ForAll(
coll,
obj => (coll.Where(x=>x.PropA = obj.PropA).Count==1)
)
);
理论是,它将coll过滤到那些PropA值与我们正在查看的对象相同的元素。应该只有其中一个(它本身)。
可以对b进行类似的重复。
它在理论上是微不足道的组合ForAll lambda表达式,但我不确定你会想要。当然,如果一个条件失败了,那么知道哪个条件失败了会更好,而不是把它们放在一起,只知道某个条件失败了,而不是真正的失败了……
如果你能在格式上给点余地,你可以试试:
Contract.Requires(
Contract.ForAll(
coll.GroupBy(x=>x.PropA),
group => group.Count==1)
)
);
这是一个类似的原则,但我认为将做计数更有效,因为组by和计数将更有效(我认为-我没有测试过,不熟悉linq方法的内部工作)。
的另一个方法:
HashSet<object> propAValues = new HashSet<object>();
Contract.Requires(
!coll.Any(x=>!hashset.Add(x.PropA))
);
使用哈希集,如果元素已经存在,则Add返回false。在这种情况下,Add生成一个false(因此lambda表达式为真),那么Any将返回真,因为它是否定的,因此测试将失败。
这个方法是否合理可能取决于你的对象有多大(因此倍增你的对象集的潜在内存影响)。然而,与这里的其他方法相比,它将花费最少的迭代来终止(因为其他方法需要查看集合中的每个对象,可能需要多次,而最后一个方法可能在查看两个条目后停止)。