2010-01-17 25 views
5

que tiene una clase como esta:C# Ejecución IEquatable <T> .Equal <T>

public class Foo<T> : IEquatable<T> where T : struct 
{ 
    List<T> lst; 
    [Other irrelevant member stuff] 
} 

que desea implementar la interfaz IEquatable<T> para la clase Foo. Que necesito hacer. Por simplicidad, quiero simplemente verificar si los miembros de la Lista son iguales.

Gracias.

Las respuestas compatibles con C# 4.0 son admisibles.

Actualización: Esto es lo que tengo actualmente:

public bool Equals(Foo<T> foo) 
{ 
    return lst.Equals(foo.lst); 
} 

public override bool Equals(Object obj) 
{ 
    if (obj == null) return base.Equals(obj); 

    if (!(obj is Foo<T>)) 
    { 
     throw new Exception("The 'obj' argument is not a Foo<T> object."); 
    } 
    else 
    { 
      return Equals(obj as Foo<T>) 
    } 
}  

public override int GetHashCode() 
{ 
    return this.lst.GetHashCode(); 
} 

public static bool operator ==(Foo<T> f1, Foo<T> f2) 
{ 
    return f1.Equals(f2); 
} 

public static bool operator !=(Foo<T> f1, Foo<T> f2) 
{ 
    return (!f1.Equals(f2)); 
} 

consigo este error:

Error 1 'Foo<T>' does not implement interface member 'System.IEquatable<T>.Equals(T) 

Respuesta

2

Prueba esto.

public class Foo<T> : IEquatable<Foo<T>> where T : struct 
    { 
     List<T> lst; 

     #region IEquatable<T> Members 

     public bool Equals(Foo<T> other) 
     { 
      if (lst.Count != other.lst.Count) 
      { 
       return false; 
      } 

      for (int i = 0; i < lst.Count; i++) 
      { 
       if (!lst[i].Equals(other.lst[i])) 
       { 
        return false; 
       } 
      } 
      return true; 
     } 

     #endregion 

     public override bool Equals(object obj) 
     { 
      var other = obj as Foo<T>; 
      return other != null && Equals(other); 
     } 


    } 
+1

Gracias. Necesitaba tener IEquatable en lugar de IEtabletable . Sabía que era algo estúpido. – Chris

+4

Esto no funcionará - List.Equals no hace lo que usted quiere. –

+0

Gracias por la corrección. Modificó la publicación original. –

12

Desafortunadamente, List<T> no anulan o EqualsGetHashCode. Eso significa que incluso cuando se haya corregido su declaración de la clase, que necesita para realizar las comparaciones de sí mismo:

public bool Equals(Foo<T> foo) 
{ 
    // These need to be calls to ReferenceEquals if you are overloading == 
    if (foo == null) 
    { 
     return false; 
    } 
    if (foo == this) 
    { 
     return true; 
    } 
    // I'll assume the lists can never be null 
    if (lst.Count != foo.lst.Count) 
    { 
     return false; 
    } 
    for (int i = 0; i < lst.Count; i++) 
    { 
     if (!lst[i].Equals(foo.lst[i])) 
     { 
      return false; 
     } 
    } 
    return true; 
} 

public override int GetHashCode() 
{ 
    int hash = 17; 
    foreach (T item in lst) 
    { 
     hash = hash * 31 + item.GetHashCode(); 
    } 
    return hash; 
} 

public override bool Equals(Object obj) 
{ 
    // Note that Equals *shouldn't* throw an exception when compared 
    // with an object of the wrong type 
    return Equals(obj as Foo<T>); 
} 

personalmente me gustaría pensar muy cuidadosamente antes de sobrecargarse == y = también!. Si haces deciden ponerlas en práctica, usted debe pensar en los casos en que uno o ambos de los valores es nulo:

public static bool operator ==(Foo<T> f1, Foo<T> f2) 
{ 
    if (object.ReferenceEquals(f1, f2)) 
    { 
     return true; 
    } 
    if (object.ReferenceEquals(f1, null)) // f2=null is covered by Equals 
    { 
     return false; 
    } 
    return f1.Equals(f2); 
} 
+0

¡Gracias! Me preguntaba cómo superar el caso 'ambos de los valores es nulo'. object.ReferenceEquals() es la respuesta. ¡Gracias! –

+0

Gracias como de costumbre. ¡Buena publicación! – Dienekes