2010-07-25 11 views
67

Próbuję napisać metodę rozszerzenia na typy liczbowe, które będą używane w ramach płynnego testowania, które buduję. Zasadniczo chcę, aby to zrobić:Ograniczenie rodzajowe pasujące do typów liczbowych

public static ShouldBeGreaterThan<T>(this T actual, T expected, string message) 
    where T : int || T: double || etc... 

Wystarczy where T : struct nie robić, ponieważ będzie również dopasować string i bool, a może coś innego ja zapominam. czy jest coś, co mogę zrobić, aby dopasować tylko typy liczbowe? (W szczególności typy, które implementują operatorów > i <, więc mogę je porównać ... Jeśli to oznacza, że ​​dopasowuję daty, to nie ma to znaczenia - rozszerzenie nadal będzie spełniało moje oczekiwania.)

+6

Jon Skeet i Mark Gravell przygotowali kilka interesujących zajęć: http://www.yoda.arachsys.com/csharp/genericoperators.html –

+10

@Dan właściwie to jest "Marc", ale odpuszczę - bardzo mało osób to rozumie, p –

Odpowiedz

48

W tym przypadku chcesz ograniczyć swój ogólny do interfejsu IComparable, który daje dostęp do metody CompareTo, ponieważ ten interfejs pozwala odpowiedzieć na pytanie ShouldBeGreaterThan.

Typy liczbowe zaimplementują ten interfejs, a fakt, że działa on również na ciągi znaków, nie powinien przeszkadzać Ci tak bardzo.

+1

To jest lepsze rozwiązanie niż bardziej ogólny interfejs operatora dla typów liczbowych, przynajmniej dla tego problemu. –

+0

Czy istnieje sposób, aby zezwolić na użycie '==' i '>' etc zamiast ".Equals()' i '.CompareTo'? –

5

Stackoverflow jest zaśmiecony tego rodzaju pytaniem. Take a look at this search. C# nie obsługuje sposobu definiowania typu ogólnego ograniczonego liczbami. Niestety najlepszym wyjściem jest zaimplementowanie metody rozszerzania na wszystkich obiektach i wykonanie przełącznika w oparciu o typ lub utworzenie zestawu metod dla int, double, float, itp.

15
public static bool IsGreaterThan<T>(this T actual, T comp) where T : IComparable<T> 
{ 
    return actual.CompareTo(comp) > 0; 
} 

Możesz również dodać wiązanie struct, jeśli chcesz.

6

Trudno jest ograniczyć się do samych liczb, ponieważ nie ma nic wspólnego, takiego jak INumeric do użycia jako filtr. Właściwie podejrzewam, że najprostszym podejściem jest tutaj , a nie naleganie na ograniczenie i użycie metody Comparer<T>.Default.Compare.

Ten wbudowany podpory zarówno ogólnego IComparable<T> i nierodzajową IComparable i wspiera ref typów, wartości typów i podnoszone poprzez wykorzystanie Nullable<T>.

Dla pełnej Operator użytkowania, spojrzeć na MiscUtil's Operator class i GreaterThan etc, które mogą być przydatne, jeśli naprawdę chcesz użyć operatora (zamiast interfejsu). Zapewnia również dostęp do innych operatorów jak Add itp

+0

Marc Gravell powiedział: "Trudno ** ograniczyć się do samych liczb", ale jest ** możliwy ** zarówno w czasie wykonywania, jak i podczas kompilacji. Proszę zobaczyć moją odpowiedź na pytanie "Czy istnieje ograniczenie, które ogranicza moją ogólną metodę do typów liczbowych?" question.https: //stackoverflow.com/questions/32664/is-there--constraint-that-restricts-my-generic-method-to-numeric- typeses –

+1

@Erez to zadziała, ale jest to śmierć Kod krytyczny wydajności - wiele kontroli boksu i typu. Gdzieś w C# 7,2-C# 8.0 prawdopodobnie zobaczymy dodatki do leków generycznych, aby zrobić to znacznie wydajniej. –

+0

Nie mogę się doczekać, aż to będzie obsługiwane przez Microsoft. –

38
where T : struct, 
      IComparable, 
      IComparable<T>, 
      IConvertible, 
      IEquatable<T>, 
      IFormattable 

to najbliżej można dostać się do ograniczenia liczbowego. Wszystkie typy liczbowe implementują te 5 interfejsów, ale IFormattable nie jest implementowany przez bool, a łańcuchy są typem referencyjnym, więc nie mają zastosowania.

Jest kilka innych rzeczy, które je implementują - na przykład DateTime, więc nie jest to tak naprawdę wymagane, ale zapobiega wielu sytuacjom, których nie chcesz.

+0

Mimo to nie mogę używać zwykłych operacji matematycznych. 'Operator '==' nie może być zastosowany do argumentów typu 'T' i 'float'' –

Powiązane problemy