2010-01-17 14 views
5

ho una classe come questa:C# implementazione IEquatable <T> .Equal <T>

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

voglio implementare l'interfaccia IEquatable<T> per la classe Foo. Cosa devo fare. Per semplicità voglio solo verificare se i membri della lista sono uguali.

Grazie.

Le risposte supportate da C# 4.0 sono consentite.

Aggiornamento: Ecco quello che ho attualmente:

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)); 
} 

ottengo questo errore:

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

risposta

2

Prova questo.

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

Grazie. Avevo bisogno di avere IEquatable anziché IEquatable . Sapevo che era qualcosa di stupido. – Chris

+4

Questo non funziona - List.Equals non fa quello che vuoi. –

+0

Grazie per la correzione. Modificato il post originale. –

12

Purtroppo, List<T> non sovrascrive Equals o GetHashCode. Ciò significa che anche quando aver corretto la vostra dichiarazione di classe, è necessario eseguire i confronti da soli:

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>); 
} 

Io personalmente pensare molto attentamente prima di sovraccarico == e = troppo!. Se fai decidere per la loro attuazione, si dovrebbe pensare a casi in cui uno o entrambi i valori è nullo:

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

Grazie! Mi stavo chiedendo come superare il caso 'entrambi i valori è nullo'. object.ReferenceEquals() è la risposta. Grazie! –

+0

Grazie come al solito. Ottimo post! – Dienekes