C#-确定列表是否<;T>;是脏的吗?

C#-确定列表是否<;T>;是脏的吗?,c#,compact-framework,c#-2.0,hash,generic-list,C#,Compact Framework,C# 2.0,Hash,Generic List,我正在序列化作为数据实体的类列表。我有一个包含列表的数据提供程序 我总是直接在集合中修改项目 确定列表中的任何项目是否已更改的最佳方法是什么?我使用的是紧凑型框架 我目前唯一的想法是在加载列表时创建列表的散列(如果可能的话)。然后,当我进行保存时,我会重新获取列表的哈希值,看看它们是否是不同的值。如果它们不同,我保存并更新存储的哈希值,以便以后比较;如果它们相同,则不保存 有什么想法吗?你可以创建自己的IList类,比如说DirtyList,它可以记录列表的更改时间。你可以实现自己的列表,它维护

我正在序列化作为数据实体的类列表。我有一个包含列表的数据提供程序

我总是直接在集合中修改项目

确定列表中的任何项目是否已更改的最佳方法是什么?我使用的是紧凑型框架

我目前唯一的想法是在加载列表时创建列表的散列(如果可能的话)。然后,当我进行保存时,我会重新获取列表的哈希值,看看它们是否是不同的值。如果它们不同,我保存并更新存储的哈希值,以便以后比较;如果它们相同,则不保存


有什么想法吗?

你可以创建自己的
IList
类,比如说
DirtyList
,它可以记录列表的更改时间。

你可以实现自己的列表,它维护两个内部列表。。。以及实例化版本和跟踪版本。。。e、 g

//Rough Psuedo Code
public class TrackedList<T> : List<T>
{
    public bool StartTracking {get; set; }
    private List<T> InitialList { get; set; }

    CTOR
    {
        //Instantiate Both Lists...
    }

    ADD(item)
    {
        if(!StartTracking)
        {
            Base.Add(item);
            InitialList.Add(item);
        }
        else
        {
            Base.Add(item);
        }
    }

    public bool IsDirty
    {
       get
       {
           Check if theres any differences between initial list and self.
       }
    }
}
//粗略的伪代码
公共类TrackedList:List
{
公共布尔开始跟踪{get;set;}
私有列表初始列表{get;set;}
执行器
{
//实例化两个列表。。。
}
添加(项目)
{
如果(!开始跟踪)
{
基础。添加(项目);
初始列表。添加(项目);
}
其他的
{
基础。添加(项目);
}
}
公共图书馆
{
得到
{
检查初始列表和self之间是否有任何差异。
}
}
}

如果您愿意使用反射,
列表
类有一个名为
\u version
的私有字段,该字段在列表每次更改时递增。它不会告诉您哪些项目已更改,但您可以将其与
\u version
的原始值进行比较,以检测未修改的列表

作为参考,此字段用于确保修改列表时枚举数无效。因此,除非
List
的实际托管代码发生更改,否则您应该能够非常可靠地将其用于您的目的

要获取
\u version
的值,您可以使用以下方法:

List<T> myList;
var field = myList.GetType().GetField("_version", BindingFlags.Instance | BindingFlags.NonPublic);
int version = field.GetValue(myList);
列出myList;
var field=myList.GetType().GetField(“_version”,BindingFlags.Instance | BindingFlags.NonPublic);
int version=field.GetValue(myList);

但总的来说,这并不是最好的方法。但是,如果你无法使用别人创建的
列表,那么这可能是你最好的选择。请注意,对.NET framework的更改可能会更改字段的名称(或将其完全删除),并且不能保证在第三方CLR实现(如Mono)中存在该字段。

如果添加到列表中的项实现了该接口,您可以为添加到列表中的所有对象构建自己的通用列表,该列表将钩住该接口中的事件,并在从列表中删除项目时取消钩住事件

框架中有一个类可以使用,也可以编写自己的类

这里是一个示例add方法,假设已使用
声明了类型,其中T:INotifyPropertyChanged

public void Add(T item)
{
    // null-check omitted for simplicity
    item.PropertyChanged += ItemPropertyChanged;
    _List.Add(item);
}
以及
此[索引]
索引器属性:

public T this[Int32 index]
{
    get { return _List[index]; }
    set {
        T oldItem = _List[index];
        _List[index] = value;
        if (oldItem != value)
        {
            if (oldItem != null)
                oldItem.PropertyChanged -= ItemPropertyChanged;
            if (value != null)
                value.PropertyChanged += ItemPropertyChanged;
        }
    }
}

如果您的项目不支持<代码> NoTyjyPrimyType ,但它们是您的类,我将考虑添加该支持。

确保T是具有脏标志的对象的后代,并且IList实现具有对列表中的脏列表的检查。p> 像这样的怎么样

public class ItemChangedArgs<T> : EventArgs
{
    public int Index { get; set; }
    public T Item { get; set; }
}

public class EventList<T> : IList<T>, ICollection<T>, IEnumerable<T>, IEnumerable
{
    private List<T> m_list;
    public event EventHandler<ItemChangedArgs<T>> ItemAdded;
    public event EventHandler<ItemChangedArgs<T>> ItemRemoved;
    public event EventHandler<ItemChangedArgs<T>> ItemChanged;
    public event EventHandler ListCleared;

    public EventList(IEnumerable<T> collection)
    {
        m_list = new List<T>(collection);
    }

    public EventList(int capacity)
    {
        m_list = new List<T>(capacity);
    }

    public EventList()
    {
        m_list = new List<T>();
    }

    public void Add(T item)
    {
        Add(item, true);
    }

    public void Add(T item, Boolean raiseEvent)
    {
        m_list.Add(item);
        if (raiseEvent) RaiseItemAdded(this.Count - 1, item);
    }

    public void AddRange(IEnumerable<T> collection)
    {
        foreach (T t in collection)
        {
            m_list.Add(t);
        }
    }

    private void RaiseItemAdded(int index, T item)
    {
        if (ItemAdded == null) return;

        ItemAdded(this, new ItemChangedArgs<T> { Index = index, Item = item });
    }

    public int IndexOf(T item)
    {
        return m_list.IndexOf(item);
    }

    public void Insert(int index, T item)
    {
        m_list.Insert(index, item);
        RaiseItemAdded(index, item);
    }

    public void RemoveAt(int index)
    {
        T item = m_list[index];
        m_list.RemoveAt(index);
        RaiseItemRemoved(index, item);
    }

    private void RaiseItemRemoved(int index, T item)
    {
        if(ItemRemoved == null) return;
        ItemRemoved(this, new ItemChangedArgs<T> { Index = index, Item = item });
    }

    public T this[int index]
    {
        get { return m_list[index]; }
        set 
        { 
            m_list[index] = value;
            RaiseItemChanged(index, m_list[index]);
        }
    }

    private void RaiseItemChanged(int index, T item)
    {
        if(ItemChanged == null) return;
        ItemChanged(this, new ItemChangedArgs<T> { Index = index, Item = item });
    }

    public void Clear()
    {
        m_list.Clear();
        RaiseListCleared();
    }

    private void RaiseListCleared()
    {
        if(ListCleared == null) return;
        ListCleared(this, null);
    }

    public bool Contains(T item)
    {
        return m_list.Contains(item);
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
        m_list.CopyTo(array, arrayIndex);
    }

    public int Count
    {
        get { return m_list.Count; }
    }

    public bool IsReadOnly
    {
        get { return false; }
    }

    public bool Remove(T item)
    {
        for (int i = 0; i < m_list.Count; i++)
        {
            if(item.Equals(m_list[i]))
            {
                T value = m_list[i];
                m_list.RemoveAt(i);
                RaiseItemRemoved(i, value);
                return true;
            }
        }
        return false;
    }

    public IEnumerator<T> GetEnumerator()
    {
        return m_list.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return m_list.GetEnumerator();
    }
}
公共类ItemChangedArgs:EventArgs
{
公共int索引{get;set;}
公共T项{get;set;}
}
公共类事件列表:IList、ICollection、IEnumerable、IEnumerable
{
私人名单;
添加了公共事件事件处理程序项;
移除公共事件事件处理程序项;
公共事件事件处理程序项已更改;
公共事件事件处理程序列表已清除;
公共事件列表(IEnumerable集合)
{
m_列表=新列表(集合);
}
公共事件列表(int容量)
{
m_列表=新列表(容量);
}
公共事件列表()
{
m_list=新列表();
}
公共作废新增(T项)
{
添加(项目,正确);
}
公共无效添加(T项,布尔值raiseEvent)
{
m_列表。添加(项目);
如果(raiseEvent)RaiseItemAdded(this.Count-1,项);
}
公共void AddRange(IEnumerable集合)
{
foreach(集合中的T)
{
m_列表。添加(t);
}
}
添加了私有void raiseItem(整数索引,T项)
{
if(ItemAdded==null)返回;
ItemAdded(这是新的ItemChangedArgs{Index=Index,Item=Item});
}
公共整数索引(T项)
{
返回m_list.IndexOf(项目);
}
公共空白插入(整数索引,T项)
{
m_列表。插入(索引,项目);
增加(索引,项目);
}
公共无效删除(整数索引)
{
T项=m_列表[索引];
移动列表(索引);
删除RAISEITEM(索引,项目);
}
私有void RaiseItemRemoved(整数索引,T项)
{
如果(ItemRemoved==null)返回;
ItemRemoved(这个,新的ItemChangedArgs{Index=Index,Item=Item});
}
公共T此[int索引]
{
获取{return m_list[index];}
设置
{ 
m_列表[索引]=值;
RaiseItemChanged(索引,m_列表[索引]);
}
}
私有void RaiseItemChanged(整数索引,T项)
{
if(ItemChanged==null)返回;
ItemChanged(这个,新的ItemChangedArgs{Index=Index,Item=Item});
}
公共空间清除()
{
m_list.Clear();
RaiseListCleared();
}
私有void RaiseListCleared()
{
if(ListCleared==null)返回;
ListCleared(此为空);
}
公共布尔包含(T项)
{
返回m_列表。包含(项);
}
public void CopyTo(T[]数组,int arrayIndex)
{
m_list.CopyTo(数组、数组索引);
}
公共整数计数
public class DirtyList<T> : List<T> {
    private IList<int> hashCodes = new List<int> hashCodes();
    public DirtyList() : base() { }
    public DirtyList(IEnumerable<T> items) : base() {
        foreach(T item in items){
            this.Add(item); //Add it to the collection
            hashCodes.Add(item.GetHashCode());
        }
    }

    public override void Add(T item){
        base.Add(item);
        hashCodes.Add(item);
    }
    //Add more logic for the setter and also handle the case where items are removed and indexes change and etc, also what happens in case of null values?

    public bool IsDirty {
       get {
           for(int i = 0; i < Count: i++){
               if(hashCodes[i] != this[i].GetHashCode()){ return true; }
           }
           return false;
       }
    }
}