gpt4 book ai didi

C# Collection.Remove(T item) 尽管对象数据相等但不起作用

转载 作者:太空宇宙 更新时间:2023-11-03 19:49:24 25 4
gpt4 key购买 nike

我有两个集合,一个用于 Book 对象,一个用于 BookViewModel 对象。当我从 BookCollection 中删除 Book 对象时,会触发 CollectionChanged 事件,以便 BookViewModelCollection 可以删除它的 BookViewModel 版本的书。所以这是绑定(bind)到事件的委托(delegate)函数。

BookViewModelCollection.cs

private void ModelCollectionChanged(Object sender, NotifyCollectionChangedEventArgs e)
{
if (syncDisabled == false)
{
syncDisabled = true;
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
foreach (var book in e.NewItems.OfType<Book>().Select(v => new BookViewModel(v)))
{
this.Add(book);
}
break;
case NotifyCollectionChangedAction.Remove:
foreach (var book in e.OldItems.OfType<Book>().Select(v => new BookViewModel(v)))
{
this.Remove(book);
}
break;
case NotifyCollectionChangedAction.Reset:
this.Clear();
break;
}
syncDisabled = false;
}
}

也许从 Book 转换为 BookViewModel 时出错?代码正在执行,但 Remove 方法返回 false,并且对象仍在集合中,尽管两个对象上的数据相同。 BookViewModel 持有 Book 类型的对象,构造函数仅执行以下操作:

BookViewModel.cs

public BookViewModel(Book b)
{
this.Book = b;
}

Book 是设置 Book 局部变量的属性。

注意:另一方面,当 BookCollectionViewModel 发生变化时更新 BookCollection 使用相同的技术非常好。

我希望有人能帮助我。如果您需要更多/其他信息,请告诉我。我也可以将文件上传到 Github。

最好的问候

最佳答案

remove 方法在 MSDN 上有这个文档:

If type T implements the IEquatable generic interface, the equality comparer is the Equals method of that interface; otherwise, the default equality comparer is Object.Equals.

因为你还没有实现 IEquatable<T> ,将使用默认的相等比较器。这意味着 Remove方法将检查您要删除的项目是否与集合中的对象之一具有相同的引用。这显然不是这种情况,因为一个项目是一个对象而另一个是不同的对象:2 个不同的引用。

foreach( var book in e.OldItems.OfType<Book>().Select( v => new BookViewModel( v ) ) ) {
this.Remove( book );
}

你在上面所做的是创建一堆 BookViewModel (s) 然后尝试将它们从您的收藏中删除。但是你刚刚创建了那个 book所以它以前从未存在于您的收藏中。

如果您希望能够做到这一点,那么您至少应该实现 IEquatable<T>你的类型上的接口(interface)所以Remove方法可以使用它来确定要删除的项目是否在集合中,但不仅使用引用相等性,还使用其他一些相等性。

这是一个 example (我复制了下面的代码)通过检查 2 个部分是否具有相同的 PartId 来进行相等性检查。即使对象是不同的对象(引用)。

using System;
using System.Collections.Generic;
// Simple business object. A PartId is used to identify the type of part
// but the part name can change.
public class Part : IEquatable<Part> {
public string PartName { get; set; }

public int PartId { get; set; }

public override string ToString() {
return "ID: " + PartId + " Name: " + PartName;
}
public override bool Equals(object obj) {
if( obj == null )
return false;
Part objAsPart = obj as Part;
if( objAsPart == null )
return false;
else
return Equals( objAsPart );
}
public override int GetHashCode() {
return PartId;
}
public bool Equals(Part other) {
if( other == null )
return false;
return ( this.PartId.Equals( other.PartId ) );
}
// Should also override == and != operators.

}

最后一点,您可能会遇到 IComparable<T>区别也是如此:

IEquatable<T>测试两个对象是否相等。这就是您所需要的。

IComparable<T>用于排序以指示在排序过程中哪个对象排在另一个对象之前。例如,要对数字 5、1 进行排序,它会告诉您 1 在 5 之前,以便进行升序排序。 IEquatable 会告诉你 1 不等于 5。

关于C# Collection<T>.Remove(T item) 尽管对象数据相等但不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41474713/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com