想象下面的类用作某些复杂请求的参数对象。使用可变对象作为散列键
public class RequestParameters
{
///<summary>Detailed User-Friendly Descriptions.</summary>
string Param1 { get; set; } = "Default";
int? Param2 { get; set; }
bool Param3 { get; set; } = true;
...
string ParamN { get; set; }
}
我希望用户能够创建并交给它关闭在请求中使用之前配置此参数对象,因为他们认为合适的:
RequestParameters _filtered = new RequestParameters();
filtered.Param1 = "yellow";
filtered.Param3 = true;
_someInstance.InvokeRequest(_filtered);
一旦我处理请求,我希望根据提供的请求参数缓存结果。这将是微不足道的实施一些克隆方法和IEquatable<RequestParameters>
,并覆盖上述RequestParameters
类Equals()
和GetHashCode()
,但后者被广泛认为是不好的做法 - RequestParameters
是可变的,如果一个实例被插入后修改,就可能乱用我的缓存。另一方面,如果我要实现某种类的ReadOnlyRequestParameters
这个类的副本,而不是使用setter,那么我觉得这将会导致大量的代码重复(以及维护头痛)。
如果我小心地制作用户发送的实例的副本,并且在插入缓存后不再修改它们,那么将此类用作缓存键会真的很糟吗?如果你是一个使用相同对象的开发者,你会提出什么选择?
如何某种工厂,在那里你收集所有参数,可能改变他们前进的道路上,并返回一个不变的副本,需求?关于“代码重复”和“维护头痛”:如何使用T4来保持工厂的读/写属性和不可变副本的只读属性同步? – Corak
你有三种选择。 (1)靠你的裤子飞行,直接使用物体,并希望没有人改变它。 (2)实现'.Freeze()'方法,以防止对对象的进一步更改,以便您可以依赖'GetHashCode' /'Equals'。 (3)创建你的课程的只读版本。 – Enigmativity
实现GetHashCode()over mutable字段的另一个问题是,它是(public)类的公共接口的一部分。客户可能希望将实例存储在他们自己的字典或HashSet中,并且他们可能会期望参考平等行为,因为该类是可变的。 – Blorgbeard