2009-06-28 2 views
1

Je fais des comparaisons d'octets [].Je veux avoir une méthode d'extension "Equals" entre les tableaux de 2 octets

J'ai essayé == mais cela est tout comme la base Equals, qui:

byte[] a = {1,2,3}; 
byte[] b = {1,2,3}; 
bool equals = a == b; //false 
equals = a.Equals(b); //false 

J'ai essayé d'ajouter une méthode d'extension, mais étant donné que la classe de base surchargée Equals prend les mêmes arguments, il va la méthode de base plutôt à l'extension, y at-il de toute façon je peux utiliser une extension Equals (sans changer son nom ...) ou (encore mieux) utiliser == opérateur?

Voici ce que j'ai fait au comparateur:

public static bool ContentEquals(this byte[] array, byte[] bytes) 
{ 
    if (array == null || bytes == null) throw new ArgumentNullException(); 
    if(array.Length != bytes.Length) return false; 
    for (int i = 0; i < array.Length; i++) 
     if (array[i] != bytes[i]) return false; 

    return true; 
} 
+0

Un timing impeccable! Je voulais faire exactement la même chose ce matin et vous et Skeet étiez là avec le Q/A :-) –

+0

heureux d'entendre ... – Shimmy

+2

Linq a déjà une méthode intégrée appelée «SequenceEqual» qui fait exactement ce que vous décrivez . – Juliet

Répondre

6
using System.Linq; 

byte[] a = {1,2,3}; 
byte[] b = {1,2,3}; 
bool same = a.SequenceEqual(b); 
7

Vous ne peut certainement pas faire la surcharge d'opérateur avec des méthodes d'extension. La raison pour laquelle cela ne fonctionne pas pour la méthode Equals est que si une méthode est applicable sans utiliser de méthodes d'extension, cette méthode sera choisie avant même que les méthodes d'extension ne soient examinées.

Même si votre méthode Equals est "meilleure" en termes de conversion des types d'argument en types de paramètres formels, le compilateur préfère toujours les méthodes "normales". Vous devrez donner un nom différent à votre méthode. Toutefois, vous pouvez toujours utiliser la méthode Enumerable.SequenceEquals. Je ne crois pas qu'il court-circuite le contrôle de longueur (même si cela pourrait, pour ICollection<T> implémentations). Vous pouvez toujours implémenter une version plus efficace. En effet, si vous venez de changer votre implémentation de tableau existant à appeler SequenceEquals ou même ArrayEquals, ce serait bien:

public static bool ArrayEquals(this byte[] array, byte[] bytes) 
{ 
    // I'd personally use braces in all of this, but it's your call 
    if (array.Length != bytes.Length) return false; 
    for (int i = 0; i < array.Length; i++)  
     if (array[i] != bytes[i]) return false; 

    return true; 
} 

Notez qu'il serait tout à fait agréable de rendre générique, mais cela aurait certainement coûté un peu de la performance que la comparaison ne pouvait être inline:

public static bool ArrayEquals<T>(this T[] first, T[] second) 
{ 
    // Reference equality and nullity checks for safety and efficiency 
    if (first == second) 
    { 
     return true; 
    } 
    if (first == null || second == null) 
    { 
     return false; 
    } 
    if (first.Length != second.Length) 
    { 
     return false; 
    }   
    EqualityComparer<T> comparer = EqualityComparer<T>.Default; 
    for (int i = 0; i < first.Length; i++) 
    { 
     if (!comparer.Equals(first[i], second[i])) 
     { 
      return false; 
     } 
    } 
    return true; 
} 
+0

Votre première méthode, non générique, ne devrait-elle pas également vérifier l'égalité de référence et la nullité? –

+0

@Tommy: Je voulais laisser la première version aussi proche de l'original que possible, mais fournir une solution plus complète avec plus de changements. –

+0

Ne vaut-il pas mieux vérifier null avant de faire la comparaison d'égalité? Ou faites-vous simplement cela en supposant que deux tableaux NULL sont considérés comme égaux? – ahawker

0

Je l'ai fait dans le même but:

static class Global 
{ 
    public static bool ArraysAreEqual(Array arr1, Array arr2) 
    { 
     if (arr1.Length != arr2.Length) 
      return false; 

     System.Collections.IEnumerator e1 = arr1.GetEnumerator(); 
     System.Collections.IEnumerator e2 = arr2.GetEnumerator(); 

     while(e1.MoveNext() && e2.MoveNext()) 
     { 
      if(!e1.Current.Equals(e2.Current)) 
       return false; 
     } 
     return true; 
    } 
} 

mais notez que le .Equals() peut même retourner false sur les types de référence quand ils sont égaux (je n'ai pas fait le test, mais vous pouvez essayer avec StringBuilder). Dans mon cas particulier je n'ai que des types de valeurs simples

+1

Sauf si vous utilisez une version .NET vraiment backwords, je ne comprends pas pourquoi vous dérangez vous-même après avoir cette réponse http://stackoverflow.com/questions/1054459/i-wanna-have-an-extension-method-equals -between-2-byte-arrays/3106129 # 3106129 – Shimmy

+0

oui, parce que je suis limité sur la version du framework .Net – sergiol

Questions connexes