c# - 我如何从字典继承但验证 Add 方法?
问题描述
如何确保在 Dictionary Generic 中,Value Attribute 始终等于 Key * 2?我用 AddItem 方法从字典中编写了一个继承类。现在,我想隐藏原来的基类?这将如何完成?或者是否有确保数据完整性的选项?这是一个简单的例子,将在工作中使用更复杂的例子
public class MultipleBy2Test:Dictionary<int, int>
{
public void AddItem(int OriginalAmount int DoubleAmount)
{
base.Add(OriginalAmount, OriginalAmount * 2);
}
}
解决方案
该Add
方法不是虚拟的,因此您不能覆盖它。剩下的唯一选择是封装字典。
public class MultipleBy2Test
{
private readonly Dictionary<int, int> _values = new Dictionary<int, int>();
public void AddItem(int originalAmount)
{
_values.Add(originalAmount, originalAmount * 2);
}
}
现在该类不继承自Dictionary<int, int>
,并且其公共接口中的任何内容都不允许访问字典。数据完整性得到了保证,因为除了您的方法之外没有任何东西可以将任何内容添加到字典中。
理想情况下,您只需添加一些方法来检索值并完成,如果这是一个选项的话。
如果您想要字典的所有其他方法,那么您将实现IDictionary<int, int>
. 由于这很麻烦,我将从通用实现开始,并使Add
方法虚拟化。这样,如果您想要另一个具有不同逻辑的字典,您不必创建另一个类并再次实现所有这些东西。
public class MyDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
private readonly IDictionary<TKey, TValue> _innerDictionary
= new Dictionary<TKey, TValue>();
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return _innerDictionary.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public virtual void Add(KeyValuePair<TKey, TValue> item)
{
_innerDictionary.Add(item);
}
public void Clear()
{
_innerDictionary.Clear();
}
public bool Contains(KeyValuePair<TKey, TValue> item)
{
return _innerDictionary.Contains(item);
}
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
_innerDictionary.CopyTo(array, arrayIndex);
}
public bool Remove(KeyValuePair<TKey, TValue> item)
{
return _innerDictionary.Remove(item);
}
public int Count => _innerDictionary.Count;
public bool IsReadOnly => _innerDictionary.IsReadOnly;
public bool ContainsKey(TKey key)
{
return _innerDictionary.ContainsKey(key);
}
public virtual void Add(TKey key, TValue value)
{
_innerDictionary.Add(key, value);
}
public bool Remove(TKey key)
{
return _innerDictionary.Remove(key);
}
public bool TryGetValue(TKey key, out TValue value)
{
return _innerDictionary.TryGetValue(key, out value);
}
public virtual TValue this[TKey key]
{
get => _innerDictionary[key];
set => _innerDictionary[key] = value;
}
public ICollection<TKey> Keys => _innerDictionary.Keys;
public ICollection<TValue> Values => _innerDictionary.Values;
}
这为您提供了一个字典实现,您可以在其中覆盖Add
方法。您可以拒绝不符合您要求的值。Add
如果您愿意,您可以创建其他重载。
public class InheritedDictionaryWithValidation : MyDictionary<int, int>
{
public override void Add(KeyValuePair<int, int> item)
{
Add(item.Key, item.Value);
}
public override void Add(int key, int value)
{
ValidateEntry(key, value);
base.Add(key, value);
}
public override int this[int key]
{
get => base[key];
set
{
ValidateEntry(key, value);
base[key] = value;
}
}
private void ValidateEntry(int key, int value)
{
if (value != key * 2)
throw new ArgumentException("You've violated some rule.");
}
}
您甚至可以更进一步避免重复并引入中间abstract
版本进行验证:
public abstract class ValidatedDictionary<TKey, TValue> : MyDictionary<TKey, TValue>
{
public override void Add(KeyValuePair<TKey, TValue> item)
{
Add(item.Key, item.Value);
}
public override void Add(TKey key, TValue value)
{
ValidateEntry(key, value);
base.Add(key, value);
}
public override TValue this[TKey key]
{
get => base[key];
set
{
ValidateEntry(key, value);
base[key] = value;
}
}
private void ValidateEntry(TKey key, TValue value)
{
if (!IsEntryValid(key, value))
throw new ArgumentException("The entry is not valid.");
}
protected abstract bool IsEntryValid(TKey key, TValue value);
}
现在,您可以创建验证条目而无需复制任何内容的字典:
public class MyIntDictionaryWithValidation : ValidatedDictionary<int, int>
{
protected override bool IsEntryValid(int key, int value)
{
return value == key * 2;
}
}
推荐阅读
- variables - 如何在字符串和 Robotframework 中使用 KSH 变量而不将其解释为案例变量
- c# - EF:如何在同一个解决方案中跨多个项目使用数据库?
- openstreetmap - 确定是十字路口还是三向路口
- python - Accuracy_score 出现错误
- java - 使用spark检索elasticsearch数据时出错
- python - 如何从巨大的 tar.gz 文件中下载文件夹?
- powershell - Powershell读取大量文本文件,过滤信息并作为一行写入其他文本文件
- sql - 使用游标执行sql查询并将其值存储在表中
- python - 从熊猫数据框文本列中获取数组的有效方法
- c# - 我想要用户的 ax value(double)。但是当试图输入 string.program 时崩溃。我该如何解决