[英]Why when i call the remove operation of this hashset it doesn't use the gethashcode neither the equality implementation?
我正在做一个应用程序来管理角色扮演会话的创建,但是我在做规则摘要的部分有问题,所以大师不必每秒钟都阅读核心书,我有这种数据结构。
用户有一个活动列表,该活动有一个场景列表,而该场景有一个冒险列表。
用户 -> Lcampaings -> Lscenaries -> Ladventures
每个活动、场景或冒险都有资源,其中包含文档、图像、资源等列表以及摘要的哈希集。
战役/场景/冒险 -> 资源 -> Ldocuments/LImages/.../HashSet 摘要
好的,所以要修改摘要,我已经实现了相等和 gethashcode
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Text;
using System.Windows;
namespace ElEscribaDelDJ.Classes
{
public class Resumenes: INotifyPropertyChanged, IEqualityComparer<Resumenes>
{
private string _nombre;
public string Nombre
{
get { return _nombre; }
set {
_nombre = value;
OnPropertyChanged("Nombre");
}
}
private string _etiquetas;
public string Etiquetas
{
get { return _etiquetas; }
set {
_etiquetas = value;
OnPropertyChanged("Etiquetas");
}
}
private string _descripcion;
public string Descripcion
{
get { return _descripcion; }
set {
_descripcion = value;
OnPropertyChanged("Descripcion");
}
}
private int _pagina;
public int Pagina
{
get { return _pagina; }
set {
if (value <= 0)
_pagina = 1;
else
_pagina = value;
OnPropertyChanged("Pagina");
}
}
private string _manual;
public string Manual
{
get { return _manual; }
set {
_manual = value;
OnPropertyChanged("Manual");
}
}
private string _manualurl;
public string ManualUrl
{
get { return _manualurl; }
set
{
_manualurl = value;
OnPropertyChanged("ManualUrl");
}
}
private string _tipoaventura;
public string TipoAventura
{
get { return _tipoaventura; }
set {
_tipoaventura = value;
OnPropertyChanged("TipoAventura");
}
}
private string _nombretipoaventura;
public string NombreTipoAventura
{
get { return _nombretipoaventura; }
set {
_nombretipoaventura = value;
OnPropertyChanged("NombreTipoAventura");
}
}
private int _indice;
public int Indice
{
get { return _indice; }
set
{
_indice = value;
OnPropertyChanged("Indice");
}
}
private List<int> _indiceslibres;
public List<int> IndicesLibres
{
get { return _indiceslibres; }
set
{
_indiceslibres = value;
OnPropertyChanged("IndicesLibres");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string PropertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
}
public bool Equals(Resumenes x, Resumenes y)
{
if (x.Nombre.Equals(y.Nombre) && x.Descripcion.Equals(y.Descripcion))
return true;
else
return false;
}
public int GetHashCode(Resumenes obj)
{
MessageBox.Show("El Hash code es " + obj.Nombre.GetHashCode());
return obj.Nombre.GetHashCode();
}
public Resumenes CopiarValores ()
{
return (Resumenes)this.MemberwiseClone();
}
}
}
(在 gethashcode 我有消息框只是为了知道是否被称为 ofc 我知道它不应该在那里)
我正在使用两个对象的名称和描述来了解它们是否相等,并使用 gethashcode 的名称。
在阅读了很多关于哈希码和相等性的工作原理的问题后,我已经这样做了,hashcodeA == hashcodeB 意味着它们可以相同,所以名称看起来很完美,这就是为什么在平等中我也使用描述,因为如果你有相同的名字和相同的描述它的摘要大致相同。
好的,所以我显示了所有摘要的列表,用户 select 一个,单击编辑,在 windows 中进行添加或编辑,我在对象的深层副本中不做一个,然后我调用例如活动编辑摘要,我删除旧的 object 并添加新的,因为我读到如果您修改了用于制作哈希码的字段,这是最好的方法。
public void EditarResumen(Resumenes resumenviejo, Resumenes resumennuevo)
{
DatosAplicacion.CampanaSeleccionada.Recursos.Resumenes.Remove(resumenviejo);
DatosAplicacion.CampanaSeleccionada.Recursos.Resumenes.Add(resumennuevo);
RecursosAplicacion.SesionUsuario.ReemplazarCampana();
}
“Datosaplicacion”是一个static class,其中有用户选择的活动,场景和冒险
using System;
using System.Collections.Generic;
using System.Text;
namespace ElEscribaDelDJ.Classes.Utilidades.Aplicacion
{
public static class DatosAplicacion
{
private static Campana _campana = new Campana();
public static Campana CampanaSeleccionada
{
get { return _campana; }
set { _campana = value; }
}
public static int IndiceCampana;
private static EscenarioCampana _escenarioseleccionado = new EscenarioCampana();
public static EscenarioCampana EscenarioSeleccionado
{
get { return _escenarioseleccionado; }
set { _escenarioseleccionado = value; }
}
public static int IndiceEscenario;
private static Aventura _aventuraseleccionada;
public static Aventura AventuraSeleccionada
{
get { return _aventuraseleccionada; }
set { _aventuraseleccionada = value; }
}
public static int IndiceAventuraSeleccionada;
}
}
resumenviejo (oldsummary) 是用
public Resumenes CopiarValores ()
{
return (Resumenes)this.MemberwiseClone();
}
这应该没问题,因为我没有任何参考 object 或类似的。
但是当我调试应用程序时,删除操作总是抛出错误,并且永远不会调用相等操作,也不会调用 gethashcode。
而且我不知道发生了什么。
我已将完整代码上传到 github https://github.com/davidgmd/Proyecto-de-fin-de-grado
您有两种方法GetHashCode
和Equals
public bool Equals(Resumenes x, Resumenes y)
public int GetHashCode(Resumenes obj)
但是它们没有覆盖框架中的正确方法,因此不会被调用。 您必须覆盖以下方法,以便框架使用它们
public override bool Equals(object obj) {
if (!(obj is Resumenes)) return false;
var other = obj as Resumenes;
return this.Nombre.Equals(other.Nombre) && this.Descripcion.Equals(other.Descripcion);
}
public override int GetHashCode() {
return this.Nombre.GetHashCode();
}
请注意, this
并不是真正需要的。 只是为了澄清一下, this
实例是与传入的other
object 进行比较的。
编辑
您可以使用IEqualityComparer<Resumenes>
的覆盖,但是您必须将其传递给哈希集的构造函数。 但是对于您放入 HashSet 以实现IEqualityComparer
的数据 object 来说,这种情况并不常见。 更好的简历应该实现Resumenes
IEquatable<T>
接口
public class Resumenes: INotifyPropertyChanged, IEquatable<Resumenes> {
public override bool Equals(object obj) { ... }
public bool Equals(Resumenes other) { ... }
public override int GetHashCode() { ... }
}
这里有几件事:
Nombre
实际上是哈希键,如果它在项目位于 hash 中时发生变化:所有赌注都关闭; 避免这种情况的一种简单方法是将其设为只读IEqualityComparer<T>
是很奇怪的; 我想知道这是否是问题的很大一部分——尤其是如果您没有将显式比较器传递到哈希集中; 但是,老实说,在这里实现IEquatable<T>
会更简单,更可取:public class Resumenes : INotifyPropertyChanged, IEquatable<Resumenes>
{
// ...
public override bool Equals(object obj) => obj is Resumenes other && Equals(other);
public bool Equals(Resumenes other)
=> other is not null && other.Nombre == this.Nombre && other.Descripcion == this.Descripcion;
public override int GetHashCode()
=> Nombre.GetHashCode();
}
您可以使用自定义相等比较器来执行此操作,但您需要将此类比较器显式传递给new HashSet<Resumenes>(comparer)
构造函数。 我希望这个比较器是一个不同类型的 singleton 实例,例如ResumenesComparer.Instance
。 使用IEquatable<T>
更加明显和方便。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.