examples ejemplos comando cadena buscar c# .net reference-type idictionary

c# - ejemplos - awk unix



Dictionary.ContainsKey()-¿Cómo funciona? (2)

He leído la documentación de MSDN sobre cómo funciona Dictionary.ContainsKey() , pero me preguntaba cómo hace la comparación de igualdad. Básicamente, tengo un diccionario con clave para un tipo de referencia * y quiero que el método ContainsKey() compruebe una determinada propiedad de ese tipo de referencia como base para determinar si la clave existe o no. Por ejemplo, si tengo un Dictionary(MyObject, int) y MyObject tiene una propiedad pública (de int ) llamada "TypeID", ¿podría obtener ContainsKey(MyObject myObject) para verificar si una de las claves tiene un TypeID que es igual a myObject ? ¿Podría simplemente sobrecargar el operador == ?

  • El tipo de referencia es un objeto llamado "Duración" que contiene un valor ( double Length ); "Duración" es un tipo de base utilizado en mi programa de música para indicar cuánto dura un sonido en particular. Derivé de él clases que incorporan conceptos de tiempo más sofisticados, como las firmas de tiempo musicales occidentales, pero quieren que todos sean comparables en términos de su longitud.

EDITAR: Como se sugirió, implementé IEquitable en mi objeto así:

public class Duration : IEquatable<Duration> { protected double _length; /// <summary> /// Gets or Sets the duration in Miliseconds. /// </summary> public virtual double Length { get { return _length; } set { _length = value; } } // removed all the other code that as it was irrelevant public override bool Equals(object obj) { Duration otherDuration = (Duration)obj; if (otherDuration._length == _length) { return true; } else { return false } } }

¿Es esto todo lo que necesito hacer?


EDITAR: aquí está el código para su ejemplo actualizado. Nota: Me parece un poco extraño que exponga el campo como protegido y que también tenga una propiedad virtual que exponga al miembro. Bajo este esquema, algo podría anular la Length lo que da como resultado una igualdad que parece que la _lenght no se comporte como se espera.

public class Duration : IEquatable<Duration> { protected double _length; /// <summary> /// Gets or Sets the duration in Miliseconds. /// </summary> public virtual double Length { get { return _length; } set { _length = value; } } // removed all the other code that as it was irrelevant public bool Equals(Duration other) { // First two lines are just optimizations if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return _length.Equals(other._length); } public override bool Equals(object obj) { // Again just optimization if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; // Actually check the type, should not throw exception from Equals override if (obj.GetType() != this.GetType()) return false; // Call the implementation from IEquatable return Equals((Duration) obj); } public override int GetHashCode() { // Constant because equals tests mutable member. // This will give poor hash performance, but will prevent bugs. return 0; } }

Consulte EqualityComparer.Default para obtener información sobre el IEqualityComparer predeterminado utilizado por la clase Dictionary.

Si no desea anular generalmente GetHashCode and Equals en la clase, o si no puede hacerlo. Existe una sobrecarga del constructor del Diccionario en el que puede proporcionar el IEqualityComparer específico para usar.

Es una interfaz sencilla de implementar, pero debe tener cuidado de respetar el contrato para GetHashCode o puede terminar con un comportamiento inesperado.

public class MyObjectEqualityComparer : IEqualityComparer<MyObject> { public bool Equals(MyObject x, MyObject y) { return x.TypeID == y.TypeID; } public int GetHashCode(MyObject obj) { return obj.TypeID; //Already an int } }

para usarlo solo ve

new Dictionary<MyObject, int>(new MyObjectEqualityComparer());

Si desea utilizar el IEqualityComparer predeterminado, debe proporcionar aproximadamente los mismos métodos en MyObjectEqualityComparer. Puede evitar anular object.Equals() si implementa IEquatable . Sin embargo, lo desaconsejaría en gran medida porque hacerlo puede crear un comportamiento sorprendente. Usted es mejor de anular Equals para que tenga un comportamiento consistente para todas las llamadas a Equals y tenga un hash que coincida con Equals. He tenido que corregir un error en el código heredado causado por un desarrollador anterior que solo implementaba IEquatable.


Dictionary interno utiliza EqualityComparer . En primer lugar, verificará si la clave implementa IEquatable . Si key no implementa esta interfaz, llamará al método Equals .