如果你想在编译时禁止修改操作,你需要一个类型安全的解决方案。
声明一个公共允许操作的接口。将该接口用作属性类型。
public interface IReadOnlyList<T>
{
T this[int index] { get; }
int Count { get; }
}
然后声明一个实现该接口并继承标准集合类的类。
public class SafeList<T> : List<T>, IReadOnlyList<T> { }
假设您正确获取了接口定义,您就不需要手动实现任何东西,因为基类已经提供了实现。使用派生类作为存储属性值的字段类型。
public class A
{
private SafeList<string> _list = new SafeList<string>();
public IReadOnlyList<string>
{
get { return _list; }
}
}
在A类中,您可以直接使用_list
,并且修改其内容。 A类的客户端只能使用通过IReadOnlyList<T>
可用的操作子集。
对于您的示例,您使用的是SortedList而不是List,因此接口可能需要调整为
public interface IReadOnlyDictionary<K, V> : IEnumerable<KeyValuePair<K, V>>
{
V this[K index] { get; }
}
我已经将其继承IEnumerable,这个接口是只读的,所以非常安全。安全类如下:
public class SafeSortedList<K, V> : SortedList<K, V>, IReadOnlyDictionary<K, V> { }
但除此之外,这是同样的想法。
更新:我刚刚注意到(出于某种我无法理解的原因),您不想禁止修改操作 - 您只想禁止某些修改操作。非常奇怪,但解决方案仍然相同。无论您想允许哪些操作,在接口中“打开它们”:
public interface IReadOnlyDictionary<K, V> : IEnumerable<KeyValuePair<K, V>>
{
V this[K index] { get; set; }
}
当然,现在接口的名称是错误的......你为什么想禁止使用 Add 方法添加,但不通过索引器禁止它呢?(索引器可用于添加项,就像 Add 方法一样。)
更新
从您的评论中,我认为您的意思是允许对现有键值对中的值进行赋值,但禁止对先前未知的键进行赋值。显然,由于键是在运行时由字符串指定的,没有办法在编译时捕获它。因此,您可能需要进行运行时检查。
public class FixedSizeDictionaryWrapper<TKey, TValue> : IDictionary<TKey, TValue>
{
IDictionary<TKey, TValue> _realDictionary;
public FixedSizeDictionaryWrapper(IDictionary<TKey, TValue> realDictionary)
{
_realDictionary = realDictionary;
}
public TValue this[TKey key]
{
get { return _realDictionary[key]; }
set
{
if (!_realDictionary.Contains(key))
throw new InvalidOperationException();
_realDictionary[key] = value;
}
}
}
如果您拥有一个普通的字典并且想将其交给某个您不信任的方法来处理,可以将其封装在其中之一中。