2010-02-10 16 views
5

tworzę rodzajowe klasy trzymać widżety i mam problemy wykonawczego zawiera metodę:Can Not Porównaj z podstawowymi wartościami

public class WidgetBox<A,B,C> 
{ 
    public bool ContainsB(B b) 
    { 
     // Iterating thru a collection of B's 
     if(b == iteratorB) // Compiler error. 
     ... 
    } 
} 

Błąd: operator „==” nie mogą być stosowane do operandy typu ' V 'i' V '

Jeśli nie mogę porównać typów, w jaki sposób mam je wprowadzić? W jaki sposób robią to słowniki, listy i wszystkie inne pojemniki generyczne?

+0

możliwy duplikat [Can not operator == być zastosowane do typów ogólnych w języku C#? (http://stackoverflow.com/questions/390900/cant-operator-be-applied-to-generic-types-in-c) – nawfal

Odpowiedz

7

masz kilka opcji tutaj

Pierwszym jest użycie Object.Equals:

if(b.Equals(iteratorB)) { 
    // do stuff 
} 

Bądź ostrożny używając tej opcji; jeśli B nie zastępuje Object.Equals, wówczas domyślne porównanie jest równością odniesienia, gdy B jest typem odniesienia i równością wartości, gdy B jest typem wartości. To może nie być zachowanie, którego szukasz i dlatego bez dodatkowych informacji rozważałbym jedną z dwóch następnych opcji.

Drugi jest dodać ograniczenie, które B jest IComparable:

public class WidgetBox<A, B, C> where B : IComparable 

tak że

if(b.CompareTo(iteratorB) == 0) { 
    // do stuff 
} 

Trzeci jest wymaga IEqualityComparer<B> przekazywane do konstruktora WidgetBox

public class WidgetBox<A, B, C> { 
    IEqualityComparer<B> _comparer; 
    public WidgetBox(IEqualityComparer<B> comparer) { 
     _comparer = comparer; 
    } 
    // details elided 
} 

Następnie:

if(_comparer.Equals(b, iteratorB)) { 
    // do stuff 
} 

Dzięki tej ostatniej opcji można podać przeciążenie, które domyślnie EqualityComparer<T>.Default:

public WidgetBox() : this(EqualityComparer<T>.Default) { } 
+1

W zależności od typu i tego, czy zależy Ci tylko na równość (w przeciwieństwie do mniejszej/większej/równej/itd.) zazwyczaj bardziej wydajne jest używanie IEqualityComparer w przeciwieństwie do programu IComparer, ponieważ równość często może być wykluczona bardzo szybko, np. z ciągami różniącymi się ent długości. – Josh

3

Nie wszystkie obiekty implementują ==, ale wszystkie będą miały wartości równe (choć mogą być dziedziczone z Object.Equals).

public class WidgetBox<A,B,C> 
{ 
    public bool ContainsB(B b) 
    { 
     // Iterating thru a collection of B's 
     if(b.Equals(iteratorB)) 
     ... 
    } 
} 
0
if (b != null) 
    if (b.Equals(iteratorB)) 
     ... 
2

w czasie kompilacji, nie ma gwarancji, że typ w argumencie typu B zapewnia operatorowi równości.

Zamiast tego, można to zrobić:

var comparer = EqualityComparer<B>.Default; 
foreach (B item in items) { 
    if (comparer.Equals(b, item)) { 
     .... 
    } 
} 
3

dodać do odpowiedzi Jasona, można również dodać where T : IEquatable<T> zamiast IComparable. Zapewnia to przeciążenie metody Equals, która akceptuje parametr T.

public class WidgetBox<A,B,C> where B : IEquatable<B> 
{ 
    public bool ContainsB(B b) 
    { 
     // Iterating thru a collection of B's 
     if(b.Equals(iteratorB)) 
     ... 
    } 
} 

Może to być korzystne, aby po prostu za pomocą dostarczonego Object.Equals metodę, ponieważ sprawdza równoważności dwóch obiektów odniesień (wierzę) i tak nie może dostarczyć sporo funkcjonalności chcesz (np, jeśli chcesz, aby dwa obiekty o tej samej Person o tej samej własności SSN były traktowane jako równe lub coś w tym stylu).

Ale żeby odpowiedzieć na twoje pytanie "jak robią to wszystkie kolekcje .NET", wierzę, że metoda Equals (bez ograniczeń) to twoja odpowiedź.

0

Jeśli można uciec z nim w twoim przypadku to wszystko, czego potrzeba, to klasa ograniczeniem B

public class WidgetBox<A,B,C> where B : class 

, które eliminują problem

Powiązane problemy