2016-03-17 2 views
3

J'ai un SortedDictionary<Package, List<string>>. Voici la classe Package:Erreur lors de l'extraction des données du dictionnaire trié en C#

using System; 

namespace GetPackageInfo 
{ 

public class Package : IComparable, IEquatable<Package> 
{ 
    public string PackageName; 
    public string Version; 

    public Package() 
    { 

    } 

    public Package(string packageName) 
    { 
     this.PackageName = packageName; 
    } 

    public override int GetHashCode() 
    { 
     unchecked 
     { 
      int result = 17; 
      result = result * 23 + ((PackageName != null) ? this.PackageName.GetHashCode() : 0); 
      result = result * 23 + ((Version != null) ? this.Version.GetHashCode() : 0); 
      return result; 
     } 
    } 

    public bool Equals(Package other) 
    { 
     if (ReferenceEquals(null, other)) 
     { 
      return false; 
     } 
     if (ReferenceEquals(this, other)) 
     { 
      return true; 
     } 
     return Equals(this.PackageName, other.PackageName) && 
       Equals(this.Version, other.Version); 
    } 

    public override bool Equals(object obj) 
    { 
     Package temp = obj as Package; 
     if (temp == null) 
      return false; 
     return this.Equals(temp); 
    } 

    public override string ToString() 
    { 
     return string.Format("PackageName: {0}, Version: {1}", PackageName, Version); 
    } 

    public int CompareTo(object obj) 
    { 
     if (obj == null) 
      return 1; 

     if (obj != null) 
      return (Equals(obj) ? -1 : 1); 
     else 
      throw new ArgumentException("Object is not a Temperature"); 
    } 

Chaque fois que je fais un Contains ou ContainsKey sur le SortedDictionary, il ne fonctionne pas même lorsque le nom et la version est la même.

if (nugetPackagesInfo.Keys.Any(p => p.Equals(package))) 
{ 
    //List<string> currPackage; 
    //nugetPackagesInfo.TryGetValue(package, out currPackage); 
    if (!nugetPackagesInfo[package].Contains(packageFile)) 
    { 
     nugetPackagesInfo[package].Add(packageFile); 
    } 

nuGetPackagesInfo est mon objet de dictionnaire. Le Any renvoie vrai si. Mais une fois qu'il est passé et obtient nugetPackagesInfo[package], alors il jette le KeyNotFoundException. Pouvez-vous s'il vous plaît m'aider à le comprendre? Est-ce que mon CompareTo n'est pas correct?

+0

* "Est-ce que mon CompareTo n'est pas correct?" * Oui. Il devrait retourner 0, <0 or > 0 en fonction de la comparaison. Votre retour -1 lors de la comparaison des objets égaux. –

Répondre

1

changement CompareTo et GetHashCode à ces mises en œuvre.

public int CompareTo(object obj) 
{ 
    if (obj == null) 
     return 1; 
    return this.ToString().CompareTo(obj.ToString()); 
} 
public override int GetHashCode() 
{ 
    unchecked 
    { 
     return ((PackageName != null ? PackageName.GetHashCode() : 0)*397)^(Version != null ? Version.GetHashCode() : 0); 
    } 
} 

public override string ToString() 
{ 
    return string.Format("PackageName: {0}, Version: {1}", PackageName??"", Version ?? ""); 
} 

CompareTo - voir le documentation. En utilisant ToString() vous obtenez une comparaison sur le nom du paquet puis sur la version sans avoir à faire vos propres vérifications. Assurez-vous simplement que ToString est correct (j'ai ajouté une vérification nulle pour ne pas lancer une exception).

GetHashCode - Je ne sais pas d'où vous avez obtenu votre implémentation. Vous devez vous assurer que le hashcode est toujours unique pour cet élément, à moins qu'ils ne soient vraiment égaux. Ceci est la mise en œuvre I found on this previous answer on SO, voir la dernière édition dans la réponse ..

+0

Merci beaucoup. Ca a marché ... J'ai généralisé le hashcode. Peut-être que c'est ce qui a mal tourné. Isnt autogénération censé fonctionner? –

+0

@ShalimaSidhik - Génial! Je ne suis pas sûr de suivre. Comment as-tu généré le hashcode? Utilisez-vous un outil ou peut-être une fonction intégrée dans Visual Studio que je ne connais pas? – Igor

+0

@ShalimaSidhik - En passant: Si vous estimez qu'une réponse est digne de la réponse à votre question, vous pouvez la marquer ainsi. Il y a une coche blanche à côté de chaque réponse, quand vous la vérifiez, elle devient verte. Vous pouvez le faire en plus des votes haut/bas que vous jugez digne/indigne en réponse. La différence est qu'une seule réponse peut être marquée comme réponse, mais vous pouvez voter vers le haut ou vers le bas pour toutes les réponses. J'écris ceci parce que j'ai vu sur votre profil que vous avez posé beaucoup de questions précédentes mais que vous n'avez jamais marqué de réponse comme réponse. – Igor

1

Votre méthode CompareTo devrait fonctionner comme ceci:

  • retour -1 si this est plus petite que obj
  • retour 1 si this est plus que obj et
  • le plus important: return 0 si thiségalobj
2

Votre implémentation de CompareTo ne semble pas être correcte. En fait, vous n'implémentez aucun commandant des packages. Vous devriez, très probablement, commander les paquets par nom, et s'ils sont égaux par version.

Le noyau de Package.CompareTo devrait ressembler à ceci (simplifié, ne pas prendre soin de other == null):

// try name ordering 
int nameOrdering = this.Name.CompareTo(other.Name); 

// names not equal ⇒ ordering is clear and no need to inspect further 
if (nameOrdering != 0) 
{ 
    return nameOrdering; 
} 
// names are equal ⇒ resort to version ordering  
else 
{ 
    return this.Version.CompareTo(other.Version); 
} 

Vous devriez également read the documentation for String.CompareTo() en raison de sa sémantique spécifique à la culture.

+0

@IvanStoev Bon point, merci. Corrigé ma réponse. –