Как я могу превратить этот простой метод в обобщенный метод c? - PullRequest
0 голосов
/ 19 апреля 2020

У меня есть следующий метод

int coerce(int val, int min=0, int max = 10)
{
    if (val < min)
        return min;
    if (val > max)
        return max;
    return val;
}

А теперь я должен сделать это для типов байтов, чисел с плавающей запятой, двойных и других чисел c типов.

Как все, что мы знаем, создание многочисленных аналогичных методов для этих типов очень неэффективно.

Поэтому я хочу превратить его в обобщенный c метод.

Ниже приведен тот, который я пытался сделать .

T coerce<T>(T val, T min=(T)0, T max=(T)10) where T:IComparable
{
    ... same as the above ...
}

Я знаю, что код не запускается, и поэтому я прошу об этом.

То, что я в настоящее время путаю, это две вещи.

Q1) Как я могу сравнить типы T? - VS предупреждает об операторе '<' и '>'. Я пытался использовать «где T: IComparable», но это не решило мою проблему.

Q2) Как я могу установить значения по умолчанию для аргумента типа generi c? - Я пытался использовать '(T) 0' и '(T) 10' для этого. Но в любом случае это был плохой выбор.

Возможно, это простой вопрос, но я не смог найти ответ от Google.

Не могли бы вы сделать мне одолжение?

Ответы [ 3 ]

2 голосов
/ 19 апреля 2020

Вы должны использовать Compare метод вместо < или > операторов. И примените правильные ограничения generi c, для числовых c типов это должно быть IComparable, IComparable<T>, IConvertible, IEquatable<T>, IFormattable. Однако вы можете оставить только where T : struct, IComparable<T>, этого должно быть достаточно для ваших целей (но здесь важно struct, поскольку вы сравниваете типы значений)

T coerce<T>(T val, T min, T max) where T : struct, IComparable, IComparable<T>, IConvertible, IEquatable<T>, IFormattable
{
    if (val.CompareTo(min) < 0)
        return min;
    if (val.CompareTo(max) > 0)
        return max;

    return val;
}

Вы также можете указать значение по умолчанию min значение типа T min = default(T), но вы не можете сделать это для значения max.

Следуя комментариям, в случае использования Nullable<T> для значений min и max код может быть написано как

T coerce<T>(T val, T? min = default, T? max = default) where T : struct, IComparable<T>
{
    var minValue = min.HasValue ? min.Value : default(T);
    var maxValue = max.HasValue ? max.Value : (T)Convert.ChangeType(10, typeof(T));

    if (val.CompareTo(minValue) < 0)
        return minValue;
    if (val.CompareTo(minValue) > 0)
        return maxValue;

    return val;
}
0 голосов
/ 19 апреля 2020

Хитрость в том, что используются методы IComparable, а не операторы сравнения. В этом случае метод CompareTo

Значения по умолчанию для параметров не прост, вы предполагаете значения чисел c и выполняете прямое приведение, но дело в том, что T может быть любым типом данных IComparable

public static T Coerce<T>(T val, T min, T max) where T:IComparable {
    if (val.CompareTo(min) < 0)
        return min;
    else if (val.CompareTo(max) > 0)
        return max;
    else
        return val;
}

Скрипка: https://dotnetfiddle.net/fJUDdR

0 голосов
/ 19 апреля 2020
public T Max<T>(T val, T min, T max) where T : IComparable<T>
{
    if (val.CompareTo(min) == -1)
        return min;

    if (val.CompareTo(min) == 1)
        return max;

    return val;
}

Деталь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...