但验证 Add 方法?,c#,.net,generics,.net-core"/>

首页 > 解决方案 > 我如何从字典继承但验证 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);
    }
}

标签: c#.netgenerics.net-core

解决方案


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;
    }
}

推荐阅读