Domanda

sto vedendo un comportamento diverso tra l'utilizzo .equals e == tra due di .NET 4.0 di nuova tupla <> istanze. Se ho sovrascritto Uguale sull'oggetto nel Tuple <> e chiamare .equals sul tuple sarà chiamato l'override di Equals. Se uso == sul Tuples l'override di Equals non è chiamato. È che la progettazione e ha senso?

Modifica Da risposte e commenti posso dire io non sono chiari. So Tuple <> è un tipo di riferimento e che per i tipi di riferimento == controllerà l'identità (ReferenceEquals). Ma, dovrebbe Tuple <> di override == per verificare l'uguaglianza degli oggetti in esso contenuti? Per coerenza, probabilmente no.

Per esempio, se ho un semplice oggetto

public class NameAndNumber
{
    public int Number { get; set; }
    public string Name { get; set; }

    public override bool Equals(object obj)
    {
        if (obj is NameAndNumber)
        {
            NameAndNumber other = (NameAndNumber)obj;
            return Number == other.Number && Name == other.Name;
        }

        return false;
    }
}

e poi faccio qualcosa di simile:

Tuple<NameAndNumber, NameAndNumber> left = new Tuple<NameAndNumber, NameAndNumber>(
      new NameAndNumber { Name = "one", Number = 1 }, 
      new NameAndNumber { Name = "two", Number = 2 });
Tuple<NameAndNumber, NameAndNumber> right = new Tuple<NameAndNumber, NameAndNumber>(
      new NameAndNumber { Name = "one", Number = 1 }, 
      new NameAndNumber { Name = "two", Number = 2 });
bool operatorResult = left == right;
bool equalsResult = left.Equals(right);
Console.Out.WriteLine("operatorResult = {0}  equalsResult = {1}", 
        operatorResult, equalsResult);

ho operatorResult = false equalsResult = true

Dovrei essere aspettavo?

So che l'attuazione degli Eguali su NameAndNumber non è "giusto" codice di esempio è solo semplificata.

Ho anche provato attuazione IEquatable, ==,! =, E GetHashCode. Stessi risultati.

È stato utile?

Soluzione

I risultati che vedete provengono da una progettazione compromesso , tuple sono ora condivisa tra F # e C #. L'importante è che tutte le tuple siano effettivamente implementati come tipi di riferimento, che non era così evidente.

La decisione se tuple dovrebbe fare controlli di uguaglianza profonde o poco profonde è stato spostato a due interfacce: IStructuralComparable, IStructuralEquatable. Si noti che quei 2 sono ora implementate anche dalla classe Array.

Altri suggerimenti

Per il tipo di riferimento: == esegue un confronto di identità, cioè tornerà vera solo se entrambi i riferimenti puntano allo stesso oggetto. Mentre si prevede che Equals () per eseguire un confronto valore, cioè esso restituisce true se i riferimenti indicano oggetti equivalenti.

Per i tipi di riferimento in cui == ha non stato sovraccaricato, confronta se due riferimenti si riferiscono allo stesso oggetto

Per impostazione predefinita, l'operatore == test per l'uguaglianza di riferimento, per cui il risultato che state vedendo è previsto.

per escludere Equals Vedere Linee Guida () e Operatore == (Guida per programmatori C # ) :

  

In C #, ci sono due tipi differenti   di uguaglianza: uguaglianza riferimento (anche   noto come l'identità) e l'uguaglianza di valore.   uguaglianza valore è il genere   capito significato di uguaglianza: è   significa che due oggetti contengono la   valori stessi. Ad esempio, due interi   con il valore di 2 hanno valore   uguaglianza. mezzi di uguaglianza di riferimento   che non vi sono due oggetti a   confrontare.

Per impostazione predefinita, == (su una classe) significa uguaglianza di riferimento; cioè essi sono lo stesso grado; ciò object.ReferenceEquals(x,y) sarebbero tornati.

È possibile fornire il proprio == / = operatori per ottenere il comportamento previsto - e quando si sostituisce Equals è importante ignorare GetHashCode troppo (altrimenti si romperà l'utilizzo come chiave - Why è importante ignorare GetHashCode quando Equals metodo viene sovrascritto in C # ):?

public static bool operator == (NameAndNumber x, NameAndNumber y) {
    if (x == null && y == null) return true;
    if (x == null || y == null) return false;
    return x.Number == y.Number && x.Name == y.Name;
    // or if polymorphism is important: return x.Equals(y);
}
public static bool operator !=(NameAndNumber x, NameAndNumber y) {
    return !(x == y); // lazy but works
}
public override int GetHashCode() {
    return (Name == null ? 0 : Name.GetHashCode()) +
        17 * Number.GetHashCode();
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top