2012-11-13 19 views
5

Kann mir jemand erklären, was in der folgenden Klassendeklaration falsch:C# generische Klasse und EqualityComparer

private class PriorityQueueEntry<TPriorityValue,IIdentifiableEntry,IType> : 
     IComparer<PriorityQueueEntry<TPriorityValue,IIdentifiableEntry,IType>> 
      where TPriorityValue : IComparable 
      where IIdentifiableEntry : Identifier<IType> 
    { 
     public TPriorityValue Priority{get;private set;} 
     public IIdentifiableEntry Entry{get;private set;} 

     public PriorityQueueEntry(TPriorityValue val,IIdentifiableEntry entry) 
     { 
      Priority = val; 
      Entry = entry; 
     } 
     public int Compare(PriorityQueueEntry<TPriorityValue,IIdentifiableEntry,IType> first, PriorityQueueEntry<TPriorityValue,IIdentifiableEntry,IType> second) 
     { 
      if (first.Priority.CompareTo(second.Priority) < 0) 
      { 
       return -1; 
      } 
      else if (first.Priority.CompareTo(second.Priority) > 0) 
      { 
       return 1; 
      } 
      return EqualityComparer<IIdentifiableEntry>.Default.Equals(first.Entry.Id, second.Entry.Id); 
     } 
    } 

Der Compiler auf der Linie complaing wo ich EqualityComparer verwenden. Der Fehler ist die folgende:

Fehler CS0176: Statischer Member `object.Equals (Object, Objekt)‘ kann nicht mit einer Instanz Referenz zugegriffen werden, qualifizieren sie mit einem Typnamen statt

Ich kann nicht sehen, wo ich eine Instanzreferenz verwende.


Entschuldigung, meine Schuld. Ich habe eine unvollständige Frage gestellt. Nur der Vollständigkeit halber ist Idetifier Klasse nur die folgenden:

public interface Identifier<ID_TYPE> 
{ 
    ID_TYPE Id{get;set;} 
} 

EqualityComparer dort verwenden, um eine Kopie und Paste Fehler zurückzuführen war (sorry Jungs, zu viel generische Code heute).

Natürlich wurde meine Frage falsch gestellt, weil ich Ihnen nicht alle Elemente gegeben habe, die Sie beantworten mussten (ich werde es bald entfernen). Ich brauchte IType zu IConvertible sein. Danke an alle auf jeden Fall.

Antwort

1

Schließlich löste ich auf diese Weise:

private class PriorityQueueEntry<TPriorityValue,IIdentifiableEntry,IType> : 
     IComparer<PriorityQueueEntry<TPriorityValue,IIdentifiableEntry,IType>> 
      where TPriorityValue : IComparable 
      where IIdentifiableEntry : Identifier<IType> 
      where IType : IConvertible 
    { 
     public TPriorityValue Priority{get;private set;} 
     public IIdentifiableEntry Entry{get;private set;} 

     public PriorityQueueEntry(TPriorityValue val,IIdentifiableEntry entry) 
     { 
      Priority = val; 
      Entry = entry; 
     } 
     public int Compare(PriorityQueueEntry<TPriorityValue,IIdentifiableEntry,IType> first, PriorityQueueEntry<TPriorityValue,IIdentifiableEntry,IType> second) 
     { 
      if (first.Priority.CompareTo(second.Priority) < 0) 
      { 
       return -1; 
      } 
      else if (first.Priority.CompareTo(second.Priority) > 0) 
      { 
       return 1; 
      } 
      return first.Entry.Id.ToUInt32(NumberFormatInfo.CurrentInfo) < first.Entry.Id.ToUInt32(NumberFormatInfo.CurrentInfo) ? -1:1; 
     } 
    } 
6

Dies ist ein Beispiel Referenz:

EqualityComparer<IIdentifiableEntry>.Default 

Das erste Problem ist, dass Sie nicht wollen object.Equals(object, object) überhaupt zu nennen. Sie möchten die Methode im Gleichheitsvergleich aufrufen, aber Sie versuchen, sie mit Argumenten aufzurufen, die nicht in IIdentifieableEntry konvertiert werden können.

Das zweite Problem ist, dass Sie einen Bestellung Vergleich auszuführen sind versucht, kein Gleichheit Vergleich, so dass Sie Comparer<T> wollen, nicht EqualityComparer<T>.

Es ist nicht klar, was Sie versuchen diesen Code zu erreichen, aber zumindest würde kompilieren:

return Comparer<IIdentifiableEntry>.Default.Compare(first.Entry, second.Entry); 

Wenn Sie wirklich die Id-Eigenschaften vergleichen wollen, können Sie einen Gleichheitsvergleich benötigen für die ID-Eigenschaftstyp - und wir wissen nicht, was dieser Typ ist.

Ich vermute, dass es wahrscheinlicher ist, dass man wirklich etwas wie diese wollen:

return Comparer<string>.Default.Compare(first.Entry.Id, second.Entry.Id); 

... aber es hängt von der Art der Id.

+6

Dieser Code da Equals nicht kompiliert gibt einen bool und die Methode sollte ein int –

+0

@WouterdeKort zurück: Ick. Danke, wird bearbeitet. –

+0

eigentlich IType: IConvertible löste meine Probleme. Entschuldigung für die unvollständige Frage. – Heisenbug

3

Sie haben die Deklaration von Identifier und EqualityComparer nicht angezeigt.Aber ich nehme an, Sie müssen wie die Linie etwas ändern:

return EqualityComparer<IIdentifiableEntry>.Default.Equals<IType>(first.Entry.Id, second.Entry.Id); 

[EDIT]

Per Jons Kommentar. Sie wollen überhaupt keinen Gleichheitsvergleich durchführen. Asumming, dass Entry.Id IComparable ist, dann nur:

return first.Entry.Id.CompareTo(second.Entry.Id); 

ich diesen Eintrag empfehlen würde, ist zu IComparable eingeschränkt, so dass wir so etwas wie:

Klasse PriorityQueueEntry> wo TPriorityValue: IComparable wo TEntry : IComparable { public TPriorityValue Priorität {get; privates set;} öffentliches TEntry Eintrag {get; privat-Set;}

public PriorityQueueEntry(TPriorityValue val, TIdentifiableEntry entry) 
    { 
     Priority = val; 
     Entry = entry; 
    } 
    public int Compare(PriorityQueueEntry<TPriorityValue, TEntry first, PriorityQueueEntry<TPriorityValue, TEntry> second) 
    { 
     if (first.Priority.CompareTo(second.Priority) < 0) 
     { 
      return -1; 
     } 
     else if (first.Priority.CompareTo(second.Priority) > 0) 
     { 
      return 1; 
     } 
     return first.Enrtry.CompareTo(second.Entry); 
    } 
} 

Sie können einige Nullprüfungen hinzufügen, wenn TEntry eine Klasse ist.

+1

'EqualityComparer ' ist eine Framework-Klasse. –

+0

'Equals' ist keine Vorlagenmethode in' EqualityComarer ' – 2kay

+0

Mein schlechtes. Ich habe es gegoogelt und es hat nur IEqualityComparer zurückgegeben. Hmmm. Bitte ignorieren Sie die vorherige Antwort. Ich werde eine neue Antwort bearbeiten. –