如果你想在编译时禁止修改操作,你需要一个类型安全的解决方案。
为公开允许的操作声明一个接口。使用该接口作为属性类型。
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;
}
}
// Implement Add so it always throws InvalidOperationException
// implement all other dictionary methods to forward onto _realDictionary
}
任何时候你有一个普通的字典,并且你想把它交给你不信任的方法来更新现有值,把它包装在其中一个中。