2011-01-04 13 views
5

mi resta che fare un semplice confronto cioèConfronta gli oggetti?

byte[] keya = System.Text.Encoding.ASCII.GetBytes("myFamilyColumn:1"); 
byte[] keyb = System.Text.Encoding.ASCII.GetBytes("myFamilyColumn:1"); 
Console.WriteLine(keya == keyb); 

ma il risultato è falso, e il loro codice hash è anche diverso, mi sto perdendo qualcosa qui?

Grazie in anticipo!

+2

Se è possibile utilizzare LINQ, è possibile eseguire 'keya.SequenceEqual (keyb)'. – Ani

+0

Purtroppo non è disponibile in mono. – Ali

+1

Non è un duplicato di [Confronta due oggetti .Net Array (matrici di byte)] (http://stackoverflow.com/q/486749/15639)? – MarkJ

risposta

11

Non credo che ci sia qualcosa nel framework che darà l'uguaglianza dell'array nel modo desiderato. Tuttavia, non è troppo difficile scrivere la propria implementazione di IEqualityComparer<T> per gli array. Per esempio (ma non testato compilati):

public static class ArrayEqualityComparer 
{ 
    public static IEqualityComparer<T[]> Create<T>(
     IEqualityComparer<T> comparer) 
    { 
     return new ArrayEqualityComparer<T>(comparer); 
    } 
} 

public sealed class ArrayEqualityComparer<T> : IEqualityComparer<T[]> 
{ 
    private static readonly IEqualityComparer<T[]> defaultInstance = new 
     ArrayEqualityComparer<T>(); 

    public static IEqualityComparer<T[]> Default 
    { 
     get { return defaultInstance; } 
    } 

    private readonly IEqualityComparer<T> elementComparer; 

    public ArrayEqualityComparer() : this(EqualityComparer<T>.Default) 
    { 
    } 

    public ArrayEqualityComparer(IEqualityComparer<T> elementComparer) 
    { 
     this.elementComparer = elementComparer;   
    } 

    public bool Equals(T[] x, T[] y) 
    { 
     if (x == y) 
     { 
      return true; 
     } 
     if (x == null || y == null) 
     { 
      return false; 
     } 
     if (x.Length != y.Length) 
     { 
      return false; 
     } 
     for (int i = 0; i < x.Length; i++) 
     { 
      if (!elementComparer.Equals(x[i], y[i])) 
      { 
       return false; 
      } 
     } 
     return true; 
    } 

    public int GetHashCode(T[] array) 
    { 
     if (array == null) 
     { 
      return 0; 
     } 
     int hash = 23; 
     foreach (T item in array) 
     { 
      hash = hash * 31 + elementComparer.GetHashCode(item); 
     } 
     return hash; 
    } 
} 

(Si noti che questo presuppone che attualmente elementComparer farà fronte con valori nulli sia GetHashCode e Equals L'interfaccia non garantisce che, ma i comparatori di uguaglianza predefinito effettivamente fanno. . gestirlo si potrebbe modificare il codice qui sopra per essere più robusto, naturalmente ... solo che non ho tempo adesso)

Usage:.

IEqualityComparer<byte[]> x = ArrayEqualityComparer<byte>.Default; 
bool equal = x.Equals(bytes1, bytes2); 

IEqualityComparer<string[]> y = 
    ArrayEqualityComparer.Create(StringComparer.OrdinalIgnoreCase); 
bool whatever = x.Equals(new[][] { "X", "Y" }, new[] { "x", "y" }); 
+0

@Jon Sono davvero sorpreso che tu non stia commentando l'uso di System.Text.Encoding.ASCII.GetBytes –

+1

@Conrad: presumo che quello sia stato il modo più semplice con il quale l'OP potesse pensare di crearne due " uguale "array di byte. –

+0

@Jon ok è giusto –

4

keya e keyb sono due oggetti completamente separati che capita di contenere gli stessi byte.

Se si desidera confrontare per vedere se due stringhe hanno gli stessi caratteri, forse si dovrebbe guardare a metodi come String.Equals?

+2

Sì, o itera attraverso gli array e confronta ogni coppia di byte. –

+0

In realtà non voglio iterare la collezione di chiavi che sono di tipo byte [] dato che conosco già la chiave e quando ottengo i byte dalla stringa non mi restituisce l'oggetto corrispondente a quella chiave ma quando uso il riferimento della chiave dall'iterazione ho trovato l'oggetto, perché è così? – Ali

+0

@Ali: Sembra che tu stia usando questi array di byte come chiavi in ​​una raccolta? Innanzitutto, se queste sono rappresentazioni di stringhe, sarebbe meglio usare le stringhe come chiavi, altrimenti, puoi scrivere il tuo comparatore di uguaglianza e dire alla collezione di usarlo al posto del default. –

1

Questa estensione generica dovrebbe fare il trucco:

public static class ArrayExtensions 
{ 
    public static bool ElementsEqual<T>(this T[] left, T[] right) 
     where T : IEquatable<T> 
    { 
     if (left == null || right == null) 
     { 
      return !(left == null^right == null); 
     } 
     else if (left.Length != right.Length) 
     { 
      return false; 
     } 

     for (int i = 0; i < left.Length; i++) 
     { 
      if (!left[i].Equals(right[i])) 
      { 
       return false; 
      } 
     } 

     return true; 
    } 
} 
1

Gli array sono tipi di riferimento in modo da testare per l'uguaglianza controlla se i puntatori sono gli stessi. Loro non sono.

Se si desidera confrontare gli elementi e non gli array stessi, è possibile import System.Linq e utilizzare keya.SequenceEqual(keyb).

+0

sfortunatamente non è disponibile in mono, che è il mio ambiente di sviluppo. – Ali

+0

@Ali: Oh, allora devi confrontare ogni elemento come le altre risposte qui. –

+0

@Ali: Credo che Mono abbia supportato LINQ to Objects per un po 'di tempo. –