În C #, care este diferența dintre modul în care operatorul == funcționează cu tipuri de referință față de primitive?


Răspunsul 1:

La fel ca în Java: == compară valorile pentru primitive, compară indicatoarele pentru referințe. Practic ==, cu excepția cazului în care supraîncărcate vor compara valorile stocate pe stivă, dacă doriți să comparați tipuri de date de referință, cum ar fi String pentru egalitate, trebuie să utilizați metoda.


Răspunsul 2:

Toate tipurile de referință acceptă == comparație: dacă nu este supraîncărcat, operatorul va efectua o verificare a egalității de referință. Dacă este supraîncărcat pentru un tip, acesta va efectua o verificare a egalității valorii, așa cum este definit de acel tip. De exemplu în C # (spre deosebire de Java) executarea == pe șiruri face o comparație de valori; în mod specific, realizează o comparație de valori Ordinal, adică o comparație caracter-caracter caracteristică, sensibilă la majuscule în caz de cultură.

Pentru încorporate în tipuri de valori primitive == are egalitatea de valoare preconizată (atenție cu float și dublu, în special NaN). Tipurile de valori definite de utilizator trebuie să definească == și! = Sau o astfel de comparație nu va fi acceptată. În general, pentru majoritatea structurilor în care are sens să doriți să comparați pentru egalitate, ar trebui:

  • define == and! = override Equals (object) override GetHashCode () implementează IEquatable și se elimină toate cele de mai sus, astfel încât fiecare metodă să ofere rezultate în concordanță cu celelalte

Răspunsul 3:

În C #, compararea primitivilor va compara valorile lor, compararea tipurilor de referință va compara referințele de reheir (implicit). Pentru tipul de referință, înseamnă că prin compararea a 2 obiecte, cu excepția cazului în care sunt exact aceeași instanță (aceeași referință), acestea nu vor fi egale:

persoană de clasă
{
  public string Nume {get;}
  
  persoană publică (numele șirului)
  {
    Nume = nume;
  }
}

Creăm 2 persoane cu același nume. Referințele lor vor fi diferite, cparisomul va rezulta în fals.

var a = Persoană nouă („Tom”);
var b = Persoană nouă („Tom”);

var areEqual = a == b; // fals

Cu toate acestea, puteți înlocui comportamentul implicit prin suprapunerea == operator:

persoană de clasă
{
  public string Nume {get;}
  
  persoană publică (numele șirului)
  {
    Nume = nume;
  }

  public static bool operator == (Persoana p1, Persoana p2)
  {
    if (Object.ReferenceEquals (p1, null)
    {
      if (Object.ReferenceEquals (p2, null)
      {
        întoarce-te adevărat;
      }
    }

    // Acum că știm că stânga nu este nulă, putem compara valorile
    returnați acest lucru.Iguale (p2);
  }

  public static bool operator! = (Persoana p1, Persoana p2) =>! (p1 == p2);

  public bool Equals (obiect p)
  {
    // Verificați dacă partea dreaptă are valoare.
    if (Object.ReferenceEquals (p, null)
    {
      returnare falsă;
    }

    // până în acest moment avem implicit == implementare.

    // Ambele referințe sunt egale înseamnă că este același obiect cu aceleași valori.
    if (Object.ReferenceEquals (aceasta, p)
    {
      întoarce-te adevărat;
    }
    
    // Tipurile trebuie să se potrivească exact.
    if (this.GetType ()! = p.GetType ())
    {
      returnare falsă;
    }
    
    // În sfârșit, putem compara conținutul fiecărui obiect.
    returnați acest lucru.Equals (p.Name);
  }
}

Acum, dacă îi comparăm din nou, rezultatul va fi adevărat.

var a = Persoană nouă („Tom”);
var b = Persoană nouă („Tom”);

var areEqual = a == b; // Adevărat