我编写了一个快速而肮脏的G集实现
public class GrowOnlySet
{
public HashSet payload {get; private set;}
public GrowOnlySet()
{
payload = new HashSet();
}
public GrowOnlySet(HashSet newstore)
{
payload = newstore;
}
public void Add(T element)
{
payload.Add(element);
}
public bool Lookup(T element)
{
return payload.Contains(element);
}
public bool Compare(GrowOnlySet R)
{
return R.payload.IsSubsetOf(this.payload);
}
public void Merge(GrowOnlySet R)
{
this.payload.UnionWith(R.payload);
}
}发布于 2018-06-19 17:38:01
我也看不出我从私生活中得到了多少。
GrowOnlySet的客户端可能以一种不适当的方式使用该对象。例如,它们可以删除元素。
所以我可以这样做,编译器允许我这样做。
var gset = new GrowOnlySet();
gset.payload.Remove("element");现在已经不再只有成长了。封装很重要。
另外,作为一个客户端,我真的不需要知道内部表示,这就是如何选择它来表示只增长的集合。
由于有效负载属性现在是公共的,所以GrowOnlySet接口有很多其他方法可以使用(通过.payload.),因此不存在抽象。但我需要一个仅由Lookup、Compare、Merge和Add方法组成的接口。
没有检查空的新商店。
public GrowOnlySet(HashSet newstore)
{
payload = newstore;
}因此,使用有效负载的方法将抛出一个不好的NullReferenceException。我更喜欢抛出一个ArgumentNullException,这样我就可以创建一个一致的GrowOnlySet,并让客户意识到他们需要提供一个新的商店。
public bool Compare(GrowOnlySet R)
{
return R.payload.IsSubsetOf(this.payload);
}这里的命名惯例。建议的名字是r.,或者可能找到一个更好的名字,比如other (受HashSet本身的启发)
this.是多余的,因此可以删除它以使代码更干净。
Compare和Merge接受null参数,但这将再次抛出NullReferenceException。更好的做法是通知这个类的客户端,它确实需要与一个对象进行比较或合并。
所以这个类被重构成这样的东西
public class GrowOnlySet
{
private readonly HashSet _payload;
public GrowOnlySet()
{
_payload = new HashSet();
}
public GrowOnlySet(HashSet newstore)
{
_payload = newstore ?? throw new ArgumentNullException(nameof(newstore));
}
public void Add(T element)
{
_payload.Add(element);
}
public bool Lookup(T element)
{
return _payload.Contains(element);
}
public bool Compare(GrowOnlySet other)
{
if (other == null) throw new ArgumentNullException(nameof(other));
return other._payload.IsSubsetOf(_payload);
}
public void Merge(GrowOnlySet other)
{
if (other == null) throw new ArgumentNullException(nameof(other));
_payload.UnionWith(other._payload);
}
}https://codereview.stackexchange.com/questions/196835
复制相似问题