封装如何修改私有成员变量,但允许访问该成员进行读取

本文关键字:成员 许访问 访问 读取 变量 何修改 修改 封装 | 更新日期: 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
        }
    }
}