Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么可观察字典是通过实现接口来实现的?_C#_Oop_Collections_Dictionary_Observablecollection - Fatal编程技术网

C# 为什么可观察字典是通过实现接口来实现的?

C# 为什么可观察字典是通过实现接口来实现的?,c#,oop,collections,dictionary,observablecollection,C#,Oop,Collections,Dictionary,Observablecollection,好的,我一直在寻找一个字典,当一段数据被更改时,它会抛出一个事件。我经常遇到的一个链接是: 在检查IDictionary接口和Dictionary类之后,我可以清楚地看到CRUD(创建-读取-更新-删除)。理论上,所有词典都应该基于此功能 在我看来,实现一个可观察的字典应该像 public class test<K,V> : Dictionary<K,V>, INotifyCollectionChanged, INotifyPropertyChanging { p

好的,我一直在寻找一个字典,当一段数据被更改时,它会抛出一个事件。我经常遇到的一个链接是:

在检查IDictionary接口和Dictionary类之后,我可以清楚地看到CRUD(创建-读取-更新-删除)。理论上,所有词典都应该基于此功能

在我看来,实现一个可观察的字典应该像

public class test<K,V> : Dictionary<K,V>, INotifyCollectionChanged, INotifyPropertyChanging
{
    public event NotifyCollectionChangedEventHandler CollectionChanged;
    public event PropertyChangedEventHandler PropertyChanged;

    private const string pCount = "Count";
    private const string pKeys = "Keys";
    private const string pValues = "Values";

    public V this[K key]
    {
        get
        {
            return base[key];
        }
        set
        {
            object old = base[key];
            base[key] = value;
            if (CollectionChanged != null)
                CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, new KeyValuePair<K, V>(key, value), new KeyValuePair<K, V>(key, (V)old)));
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(pValues));
        }
    }

    public override void Add(K key, V value)
    {
        base.Add(key, value);
        if(CollectionChanged!=null)
            CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, new KeyValuePair<K,V>(key, value)));
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(pCount));
            PropertyChanged(this, new PropertyChangedEventArgs(pKeys));
            PropertyChanged(this, new PropertyChangedEventArgs(pValues));
        }
    }

    public override void Remove(K key)
    {
        object removed = base[key];
        base.Remove(key);
        if (CollectionChanged != null)
            CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, removed));
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(pCount));
            PropertyChanged(this, new PropertyChangedEventArgs(pKeys));
            PropertyChanged(this, new PropertyChangedEventArgs(pValues));
        }
    }
}
公共类测试:字典、INotifyCollectionChanged、inotifyPropertyChanged
{
公共事件通知CollectionChangedEventHandler CollectionChanged;
公共事件属性更改事件处理程序属性更改;
私有常量字符串pCount=“Count”;
private const string pKeys=“Keys”;
private const string pValues=“Values”;
公共V本[K键]
{
得到
{
返回基[键];
}
设置
{
对象旧=基[键];
基[键]=值;
如果(CollectionChanged!=null)
CollectionChanged(此,新的NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace,新的KeyValuePair(键,值),新的KeyValuePair(键,(V)旧));
if(PropertyChanged!=null)
PropertyChanged(这是新的PropertyChangedEventArgs(pValues));
}
}
公共覆盖无效添加(K键,V值)
{
添加(键、值);
如果(CollectionChanged!=null)
CollectionChanged(此,新的NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add,新的KeyValuePair(键,值));
if(PropertyChanged!=null)
{
PropertyChanged(此为新PropertyChangedEventArgs(pCount));
PropertyChanged(即新PropertyChangedEventArgs(pKeys));
PropertyChanged(这是新的PropertyChangedEventArgs(pValues));
}
}
公共覆盖无效删除(K键)
{
移除的对象=基[键];
底座。移除(键);
如果(CollectionChanged!=null)
CollectionChanged(此,新的NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove,removed));
if(PropertyChanged!=null)
{
PropertyChanged(此为新PropertyChangedEventArgs(pCount));
PropertyChanged(即新PropertyChangedEventArgs(pKeys));
PropertyChanged(这是新的PropertyChangedEventArgs(pValues));
}
}
}
编辑:添加更多内容,使其更像示例,并帮助澄清问题

我不明白为什么所有这些精巧的词典都在制作中,有什么我遗漏的吗?有人能给我解释一下吗


就我所见,他们好像都在重新发明轮子,这与可重用代码背道而驰,而可重用代码正是OO的重点。我真的觉得我一定错过了什么。

INotifyPropertyChanged和INotifyCollectionChanged的要点在于它们是由.Net自己使用的(比如WPF和winforms)


您自己的自定义
OnValueAdd
等。委托在您自己的类之外是未知的,并且它们不能被.Net的自动更改通知机制使用。

INotifyPropertyChanged和
INotifyCollectionChanged
的要点是它们被.Net自己的类使用(例如WPF,在较小程度上是winforms)


您自己的自定义
OnValueAdd
等。在您自己的类之外不知道委托,并且.Net的自动更改通知机制无法使用它们。

您无法执行您尝试执行的操作有以下几个原因:

索引器、添加和删除方法不是虚拟的。您不能
重写
Add
Remove
方法,因为它们不是虚拟的

因为您没有覆盖这些方法,所以只要将对象键入
IDictionary
Dictionary
类型,事件就不会被触发,充其量只能对它们进行阴影处理


通过使用组合而不是继承,如您链接到的示例所示,给定字典对象的人无法在不触发事件的情况下添加项目,因为无法直接访问字典。

有几个原因导致您无法执行您尝试执行的操作:

索引器、添加和删除方法不是虚拟的。您不能
重写
Add
Remove
方法,因为它们不是虚拟的

因为您没有覆盖这些方法,所以只要将对象键入
IDictionary
Dictionary
类型,事件就不会被触发,充其量只能对它们进行阴影处理


通过使用组合而不是继承,如您链接到的示例所示,给定字典对象的人无法在不触发事件的情况下添加项目,因为无法直接访问字典。

您的示例未实现
inotifPropertyChanged
inotifCollectionChanged
。您的示例没有实现
INotifyPropertyChanged
INotifyCollectionChanged
。我认为,我对该特定实现的了解不够,这让我稍微偏离了这个问题。我想说的是,作者可以简单地从字典继承,然后扩展类来添加这些新内容。我只是不明白为什么每个这样做的人都会重新创建整个dictionary对象,尤其是当大多数重新创建的类都只是包装原始类时。@Aelphaeis在该示例中,不仅仅是在项目被删除/添加到dictionary时通知。我编辑了问题以添加什么内容我已经看到他有我没有的,并且让我更清楚地知道我说的是什么意思,就像他们在重新发明轮子一样