封装如何修改私有成员变量,但允许访问该成员进行读取
本文关键字:成员 许访问 访问 读取 变量 何修改 修改 封装 | 更新日期: 2023-09-27 18:00:07
这是一个非常基本的OOP问题。我不想复制_objectSettings
,感觉自己在脑子里放屁。这个问题可以在对象的Getter函数中看到。
示例:
public class CoolObject
{
private Dictionary<long, bool> _objectSettings;
public CoolObject(){
//.. do stuff//
}
public void UpdateSettings(long, bool){
// enforce new setting obey's some rules
}
public Dictionary<long,bool> GetSettings(){
// return Dictionary of settings, but not allow users to modify _objectSettings
}
}
谢谢:)
编辑:我上了。Net 4.0,所以我选择的答案可能不能反映出未来读者的最佳解决方案。
复制字典或将字典包装在ReadOnlyDictionary
中。NET 4.5是必需的,但如果你不在上,你可以很容易地实现自己的。净4.5。
public Dictionary<Int64, Boolean> GetSettings()
{
// Return a snapshot of the current settings.
return new Dictionary<Int64, Boolean>(this._objectSettings);
}
public ReadOnlyDictionary<Int64, Boolean> GetSettings()
{
// Return a read-only wrapper around the current settings.
return new ReadOnlyDictionary<Int64, Boolean>(this._objectSettings);
}
所有调用方都将使用后面的选项看到对设置的修改,而使用前面的选项将看不到在获取快照后对设置所做的修改。
如果您希望在自己的代码库中防止无意的修改,上述两种选项都可以,但您也可以通过使返回类型为IReadOnlyDictionary<TKey, TValue>
或IEnumerable<KeyValuePair<TKey, TValue>>
来获得较弱的保护形式。调用者可以直接转换回Dictionary<TKey, TValue>
并进行修改,但这在您自己的代码库中并不是什么大问题。
public IReadOnlyDictionary<Int64, Boolean> GetSettings()
{
// Just return the dictionary with property type IReadOnlyDictionary`2 but
// then evil callers can still do the following.
// ((Dictionary<Int64, Boolean>)coolObject.GetSettings()).Clear();
return this._objectSettings;
}
如果您将对象暴露给第三方代码,例如潜在的恶意插件,那么您确实希望避免这种情况。此外,您将不得不撤销反射权限,因为否则第三方代码仍然可能会占用您的私人词典,或者打开只读包装并对其进行修改。
尝试返回一个IReadOnlyDictionary。
public IReadOnlyDictionary<long,bool> GetSettings(){
return _objectSettings;
}
该接口由Dictionary实现,不允许对Dictionary进行更改。
[SerializableAttribute]
[ComVisibleAttribute(false)]
public class Dictionary<TKey, TValue> : IDictionary<TKey, TValue>,
ICollection<KeyValuePair<TKey, TValue>>, IDictionary, ICollection,
IReadOnlyDictionary<TKey, TValue>, IReadOnlyCollection<KeyValuePair<TKey, TValue>>,
IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable, ISerializable,
IDeserializationCallback
您可以通过使setter私有化并通过构造函数注入值来使类不可变。
public class CoolObject
{
public CoolObject(ImmutableSortedDictionary<long, bool> objectSettings){
ObjectSettings = objectSettings;
//.. do stuff//
}
public ImmutableSortedDictionary<long,bool> ObjectSettings
{
get
{
// return Dictionary of settings, but not allow users to modify _objectSettings
}
private set
{
// enforce new setting obey's some rules
}
}
}