2015-04-15 6 views
1

Я хочу написать метод расширения, который сравнивает значение с двумя другими значениями и определяет, находится ли значение в двух других. Это работает для этой целиСопоставимые и Nullable ограничения на один общий

public static bool IsWithin<T>(this T value, T min, T max) where T : IComparable<T> 
{ 
    return (bool)(value.CompareTo(min) > 0 && value.CompareTo(max) < 0); 
} 

Я также хотел бы расширить этот метод, чтобы работать на Nullable<T>. Я хотел бы, чтобы любое граничное условие игнорировалось, если значение равно null. Я попытался поставить дополнительное ограничение на T, но это не поддерживается. Следующий код не компилируется, но это то, чего я хочу достичь.

public static bool IsWithinInclusive<T>(this T value, Nullable<T> min, Nullable<T> max) where T : IComparable<T> 
{ 
    return (bool)(
     (min.HasValue ? value.CompareTo(min) >= 0 : true) && 
     (max.HasValue ? value.CompareTo(max) <= 0 : true)); 
} 

Возможно ли написать один метод, который достигает этого?

+1

Вам не нужно бросание к 'BOOL ', и вы можете заменить' a? b: true' с 'a && b' – SLaks

+1

' a && b' является ложным, когда 'min' равно null, я хочу, чтобы оно было истинным. Я что-то пропустил? – djv

+1

Тогда вы хотите '! A || b'. – SLaks

ответ

4

Вы должны ограничить T быть struct, чтобы соответствовать definition of Nullable<T>:

public static bool IsWithinInclusive<T>(this T value, Nullable<T> min, Nullable<T> max) where T : struct, IComparable<T> 
{ 
    return 
     (min.HasValue ? value.CompareTo(min.Value) >= 0 : true) && 
     (max.HasValue ? value.CompareTo(max.Value) <= 0 : true); 
} 

Вы также должны использовать .Value, чтобы получить T от Nullable<T>.

2

Как ответили SLaks, причина, по которой Nullable<T> (или только T?) не принимается, потому что для этого требуется T, чтобы быть недействительным. Вы не можете использовать один метод, который охватывает значения и ссылочные типы: типы значений, которые вы хотите поддерживать, не могут представлять null, а ссылочные типы не могут поддерживать T?, поэтому вы не можете избежать использования двух отдельных методов.

Однако, вы можете использовать ту же самую функцию тела в два раза, чтобы сделать это очевидным для читателя, что два перегруженных делать то же самое:

public static bool IsBetween<T>(this T value, T min, T max) where T : IComparable<T> 
{ 
    return (min == null || value.CompareTo((T)min) >= 0) 
     && (max == null || value.CompareTo((T)max) <= 0); 
} 

public static bool IsBetween<T>(this T value, T? min, T? max) where T : struct, IComparable<T> 
{ 
    return (min == null || value.CompareTo((T)min) >= 0) 
     && (max == null || value.CompareTo((T)max) <= 0); 
} 
+0

Хорошее объяснение, мне было интересно, нужны ли мне два метода. И у вас есть логика, как я этого хотел. Благодарю. – djv

Смежные вопросы