2012-11-13 23 views
5

Czy ktoś może mi wyjaśnić, co się dzieje w poniższej deklaracji klasy:C# rodzajowe klasy i 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); 
     } 
    } 

Kompilator complaing na linii, gdzie używam EqualityComparer. Błąd jest następujący:

error CS0176: statyczne członek `object.Equals (obiekt, obiekt)” nie można dostępne z odniesieniem instancji zakwalifikować go z nazwą typu zamiast

Nie widzę, gdzie używam odwołania do instancji.


Przykro mi, moja wina. Napisałem niepełne pytanie. Tylko dla kompletności, klasa Idetifier tylko następujące:

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

użyciu EqualityComparer nie było powodu kopiowania i wklejania pomyłkę (sorry chłopaki, zbyt wiele kodów generycznych dziś).

Oczywiście moje pytanie było błędne, ponieważ nie podałem ci wszystkich elementów, na które musiałaś odpowiedzieć (wkrótce je usunę). Potrzebowałem IType, aby być IConvertible. Dziękuję wszystkim.

Odpowiedz

1

końcu rozwiązany w ten sposób:

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

Jest to odniesienie instancja:

EqualityComparer<IIdentifiableEntry>.Default 

Pierwszym problemem jest to, że nie chcą robić zadzwonić object.Equals(object, object) w ogóle. Naprawdę chcesz wywołać metodę na porównywarce równości - ale próbujesz wywołać ją z argumentami, które nie są zamienne do IIdentifieableEntry.

Drugim problemem jest to, że starasz się wykonać porównanie zamawiania, a nie do porównywania równość, więc chcesz Comparer<T> nie EqualityComparer<T>.

Nie jest jasne, co starasz się osiągnąć, ale kod ten będzie przynajmniej skompilować:

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

Jeśli naprawdę chcesz porównać właściwości ID, potrzebujesz porównywarka równości dla Typ właściwości ID - i nie wiemy, jaki to typ.

Podejrzewam, że bardziej prawdopodobne jest, że naprawdę chcesz coś takiego:

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

... ale to zależy od rodzaju Id.

+6

Ten kod nie będzie kompilować od równymi zwraca bool i metoda powinna zwracać int –

+0

@WouterdeKort: Ick. Dzięki, edytuje. –

+0

faktycznie IType: IConvertible rozwiązał moje problemy. Przepraszamy za niepełne pytanie. – Heisenbug

3

Nie pokazałeś deklaracji identyfikatora ani EqualityComparer.Ale zakładam, trzeba zmienić linię do czegoś jak:

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

[EDIT]

Zgodnie komentarz Jona. W ogóle nie chcesz porównywać równości. Asumming że Entry.Id jest IComparable, a potem po prostu:

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

Polecam że wejście jest ograniczone do IComparable, więc coś takiego:

klasy PriorityQueueEntry> gdzie TPriorityValue: IComparable gdzie Tentry : IComparable { publicznej Priorytet TPriorityValue {get; prywatny zestaw;} publicznego Tentry Wejście {get; private 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); 
    } 
} 

Możesz chcieć dodać kilka sprawdzeń zerowych, jeśli TEntry jest klasą.

+1

'EqualityComparer ' jest klasą szkieletową. –

+0

'Equals' nie jest szablonem w' EqualityComarer ' – 2kay

+0

My bad. Przeszukałem go i przywróciłem tylko IEqualityComparer. Hmmm. Proszę pominąć poprzednią odpowiedź. Będę edytować nową odpowiedź. –