2009-06-23 9 views
5

ja nie rozumiem, co się tu dzieje ...C# boks enum błąd z rodzajowych

Mam następujący błąd: Typ 'TestApp.TestVal' nie może być używany jako typ parametru 'T' w rodzaju generycznego lub metoda 'TestApp.SomeClass<T>'. Nie ma konwersji boksu z 'TestApp.TestVal' na 'System.IComparable<TestApp.TestVal>'.

Ten błąd zdarza następującego kodu:

public enum TestVal 
{ 
    First, 
    Second, 
    Third 
} 

public class SomeClass<T> 
    where T : IComparable<T> 
{ 
    public T Stored 
    { 
     get 
     { 
      return storedval; 
     } 
     set 
     { 
      storedval = value; 
     } 
    } 
    private T storedval; 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     //Error is on the next line 
     SomeClass<TestVal> t = new SomeClass<TestVal>(); 
    } 
} 

Ponieważ enum jest int domyślnie i INT implementować interfejs IComparable<int> Wydaje się, że nie powinno być błąd ....

+0

int wdrażają IComparable ale to nie znaczy, RandomEnumType implementuje IComparable . – AakashM

Odpowiedz

8

Po pierwsze, nie jestem pewien, czy rozsądnie jest używać IComparable<T> z enum ... IEquatable<T>, jasne - ale porównanie?

Jako bezpieczniejsza alternatywa; zamiast mandatu IComparable<T> z ogólnym ograniczeniem, być może użyj klasy Comparer<T>.Default. Ma to tę zaletę, że obsługuje IComparable<T> i IComparable - i oznacza to, że masz mniej ograniczeń do propagacji.

Na przykład:

public class SomeClass<T> { // note no constraint 
    public int ExampleCompareTo(T other) { 
     return Comparer<T>.Default.Compare(Stored, other); 
    } 
    ... [snip] 
} 

To działa prawidłowo z wyliczenia:

SomeClass<TestVal> t = new SomeClass<TestVal>(); 
t.Stored = TestVal.First; 
int i = t.ExampleCompareTo(TestVal.Second); // -1 
+0

Dzięki za ewentualne alternatywne rozwiązanie mojego problemu. Rzeczywisty kod jest bardzo głęboki w strukturze testowej, która musi obsługiwać prawie każdy typ danych testowych. Będę musiał zrobić trochę więcej badań, ale wydaje się, że twój kod może być lepszym sposobem radzenia sobie z porównaniem w moich ogólnych obiektach .... –

+0

Fajna sztuczka dzięki! –

0

W języku C# implementuje implementację IComparable, ale nie jest generyczna IComparable<T>. Nie jestem pewien, dlaczego tak jest, ale może mógłbyś przełączyć się na nietypowy IComparable w swoim klauzuli where.

5

Obliczenia nie pochodzą z System.Int32s - wywodzą się z System.Enum, który nie implementuje IComparable<int> (mimo to implementuje IComparable).

Mimo że podstawową wartością enum jest int domyślnie, samo wyrażenie nie jest. Tak więc nie ma konwersji między tymi dwoma.

+0

(Naprawiłem przeciążenie - a potem oszalałem i zredagowałem twoją odpowiedź zamiast mojej własnej! Naprawiono teraz, przepraszam za to ...) –

+0

Dzięki za wyjaśnienie. To pomaga. To również sprawia, że ​​zastanawiam się, czy będę miał taki sam problem z structs .... –

0

Enum nie implementuje IComparable<T>, ale to nie realizować IComparable. Więc enum może być T w WHERE jak:

where T : IComparable 

ale daje to błąd:

where T : IComparable<T> 

I wtedy przypuszczać chcesz SomeClass być porównywalne. Aby to zrobić, musiałby wdrożyć samą funkcję IComparable.

Oto przykład z obu (za pomocą elementu publicznego zachować prosty kod):

public class SomeClass<T> 
    : IComparable<SomeClass<T>> 
    where T : IComparable 
{ 
    public T storedval; 

    public int CompareTo(SomeClass<T> other) 
    { 
     return storedval.CompareTo(other.storedval); 
    } 
}