2010-07-20 19 views
9

Ich versuche, eine einfache Klammer zu erstellen (so dass ich die Werte von etwas vergleichbares ... meist für Zahlstypen wie int, double, etc.)Nullable generischer Typ, der mit IComparable verwendet wird. Ist es möglich?

Das Problem ist, wenn ich Folgendes tue Ich erhalte einen Fehler, aber according to MSDN IComparable's CompareTo soll Nullwerte verarbeiten können.
Quote: "Per Definition vergleicht jedes Objekt größer als Null, und zwei Null-Referenzen vergleichen einander."

public static T Clamp<T>(this T value, T min, T max) 
    where T : IComparable<T> 
{ 
    if (value.CompareTo(max) > 0) 
     return max; 

    if (value.CompareTo(min) < 0) 
     return min; 

    return value; 
} 



private Int32? _zip; 
public Int32? Zip 
{ 
    get 
    { 
     return _zip; 
    } 
    set 
    { 
     _zip = value.Clamp<Int32?>(0, 99999); 
    } 
} 

Antwort

7

Denken Sie daran, Int32? ist eine Abkürzung für Nullable<Int32>. Da Nullable<T> nicht implementiert IComparable<T>, wird Ihr Code, wie strukturiert, nicht kompilieren.

Sie können jedoch überlasten die Methode:

public static T? Clamp<T>(this T? value, T? min, T? max) 
    where T : struct, IComparable<T> 
{ 
    // your logic... 
} 

Natürlich, wenn Sie auf die Arbeit mit Nullable Types planen, müssen Sie festlegen, wie Sie null Werte festklemmen ...

Wenn Sie nicht wirklich brauchen null Werte zu klemmen, kann es einfacher sein, nur erste Prüfung auf null in Ihrer Eigenschaft Getter:

public Int32? Zip 
{ 
    ... 
    set 
    { 
     _zip = value == null ? value : value.Value.Clamp<Int32>(0,99999); 
    } 

Oder noch besser, macht es im Rahmen der Umsetzung der zusätzlichen Überlastung Clamp ...

+0

Ich bin mir nicht sicher, warum ich nicht nur getan habe (Wert == null)? Wert: Wert. Klammer (0, 99999); beginnen mit. Ich glaube, ich habe nur versucht, die Clamp zu zwingen, es automatisch zu machen. Aber ja, es macht eigentlich mehr Sinn, es nicht auf Null zu setzen, da es klemmt. –

+0

Und jetzt wird es nicht für String funktionieren))) –

12

sagte Wie @LBushkin Nullable < T> oder T? implementiert IComparable-Schnittstelle nicht. Die angegebene Lösung ist in Ordnung, jedoch bevorzuge ich die NULL-fähige Vergleichslogik innerhalb einer spezialisierten Klasse in dieser Angelegenheit, die der Single Responsibility Principle folgt, und auch als Vergleich für alle Nullable-Typen verwendet werden kann.

Zum Beispiel könnten Sie eine generische Nullable Typ comparer Klasse wie folgt erstellen:

public class NullableComparer<T> : IComparer<Nullable<T>> 
     where T : struct, IComparable<T> 
{ 

    public int Compare(Nullable<T> x, Nullable<T> y) 
    { 
     //Compare nulls acording MSDN specification 

     //Two nulls are equal 
     if (!x.HasValue && !y.HasValue) 
      return 0; 

     //Any object is greater than null 
     if (x.HasValue && !y.HasValue) 
      return 1; 

     if (y.HasValue && !x.HasValue) 
      return -1; 

     //Otherwise compare the two values 
     return x.Value.CompareTo(y.Value); 
    } 

} 

In diesem Fall würden Sie diese Klasse wie folgt verwenden:

public static T? Clamp<T>(this T? value, T? min, T? max) 
    where T : struct 
{ 
    var comparer = new NullableComparer<T>(); 

    if (comparer.Compare(value, max) > 0) 
     return max; 

    if (comparer.Compare(value, min) < 0) 
     return min; 

    return value; 
} 

Praktisch für in Ihre Helfer Spar Bibliothek.

Hoffe es hilft!