我有一个类型的集合:
Iesi.Collections.Generic
public ISet<ItemBinding> ItemBindings { get; set; }
其中 ItemBinding
是 Domain.Model
我用这种方式初始化集合:
ItemBindings = new HashedSet<ItemBinding>();
我用成员填充了集合。
当我想从该集合中删除某个项目时,我无法将其删除。
private void OnRemove(ItemBinding itemToRemove) {
ItemBindings.Remove(itemToRemove);
}
甚至 itemToRemove
也与集合中的项目具有相同的 hashCode
。
我还尝试在集合中查找该项目,将其保存在变量中,然后将其删除:
private void OnRemove(ItemBinding itemToRemove) {
var foundItem = ItemBindings.Single( x => x.Id == itemToRemove.Id); // always if found
ItemBindings.Remove(foundItem);
}
但这不起作用。
一个可行的解决方法是:
private void OnRemove(ItemBinding itemToRemove) {
var backUpItems = new List<ItemBinding>(ItemBindings);
backUpItems.Remove(itemToRemove);
ItemBindings.Clear();
ItemBindings.AddAll(backUpItems);
}
但这是一个肮脏的解决方法。我正在尝试以优雅的方式执行此简单的删除:)。
更改类型
如果我更改 IList 中 ISet 的类型,它就可以正常工作。
public IList<ItemBinding> ItemBindings { get; set; }
ItemBindings = new List<ItemBinding>();
当我想从此集合中删除某个项目时,它已被删除。
private void OnRemove(ItemBinding itemToRemove) {
ItemBindings.Remove(itemToRemove);
}
我无法从 ISet 中删除项目,所以缺少什么...?
感谢您的建议和解决方案。
最佳答案
这是一个非常简单的问题。只需下载 dotPeek 1.2 并启动符号服务器,然后您就可以检查 ISet.Remove() 的实际实现并了解它为何如此挑剔。正如@HansPassant所说,这可能是GetHashCode()的情况,或者是HashedSet的实际实现
至于我的猜测;看一下 DictionarySet
(HashedSet
的基类):
如您所见,Remove() 使用 Contains() 来实际测试是否应该删除元素。 Contains() 的作用是什么?基本上它是 Dictionary.Contains() 的包装
http://msdn.microsoft.com/en-us/library/ms182358(v=vs.80).aspx
GetHashCode returns a value based on the current instance that is suited for hashing algorithms and data structures such as a hash table. Two objects that are the same type and are equal must return the same hash code to ensure that instances of System.Collections.HashTable and System.Collections.Generic.Dictionary work correctly.
请注意,重要的是:
1) 您的 GetHashCode() 无法更改。这意味着 GetHashCode() 使用的所有字段都不能更改。一旦您将元素插入到 Dictionary 中,就会调用其 GetHashCode() 并将其放入特定的存储桶中。当您以后有不同的GetHashCode()时,您将无法恢复它。 GetHashCode() 通过后,将调用您的 Equals 方法。确保您的字段是不可变的。
词典相关来源:
private int FindEntry(TKey key)
{
if ((object) key == null)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
if (this.buckets != null)
{
int num = this.comparer.GetHashCode(key) & int.MaxValue;
for (int index = this.buckets[num % this.buckets.Length]; index >= 0; index = this.entries[index].next)
{
if (this.entries[index].hashCode == num && this.comparer.Equals(this.entries[index].key, key))
return index;
}
}
return -1;
}
查看此线程如何重写 Equals() 和 GetHashCode():
Why is it important to override GetHashCode when Equals method is overridden?
请注意 @Albic 在该线程中的回答。
关于c# - 无法从 Iesi.Collections.Generic ISet<T> 中删除项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22858343/