Почему компилятор не принимает эту универсальную функцию? - PullRequest
2 голосов
/ 21 августа 2011
public static T clipGN<T>(this T v, T lo, T hi) where T : decimal,double
{ return Math.Max(lo, Math.Min(hi, v)); }

дает для второй строки:

Argument 1: cannot convert from 'T' to 'decimal'

Почему?Я думал, что оба типа встречают, что ограничение T может быть преобразовано в десятичное число.

Кстати, приемлемый альтернативный код можно найти в ответе здесь: Как лучше всего перекодировать этот пример метода расширения, чтобы он был универсальным длявсе числовые типы?

Ответы [ 2 ]

1 голос
/ 21 августа 2011

Я попытался скомпилировать этот код сам и получаю следующую ошибку:

'double' не является допустимым ограничением. Тип, используемый в качестве ограничения, должен быть интерфейсом, незапечатанным классом или параметром типа. (CS0701)

То же самое для decimal. Это говорит о том, что ни decimal, ни double не могут ограничивать параметр типа T, поскольку единственными типами, которые могли бы удовлетворить это ограничение, являются сами по себе (это не отличалось бы от создания неуниверсальной перегрузки, заменив T на decimal или double). Даже если по отдельности им было разрешено ограничить T (а это не так), комбинированное ограничение все равно не должно быть разрешено, поскольку ни один тип не может одновременно быть decimal и double.

Это не похоже на то, что ограничение прочитало where T : IComparable<T>, где оба типа, а также другие типы могут соответствовать этому ограничению.

1 голос
/ 21 августа 2011

Вам не нужны генерики для этого.В то время как концепция «СУХОЙ» делает идею кодирования единственной функции, которая может работать для всех типов, в этом случае вам лучше иметь дискретные функции для каждого числового типа.Все числовые типы известны, и список не слишком велик;скорее всего, есть числовые типы, которые вы на самом деле не собираетесь использовать .Если вы действительно (по какой-либо причине) хотите использовать одну функцию, то единственной реальной опцией является опция IComparable, к которой вы привязаны, что приводит к печальным (и ненужным) последствиям, приводящим к созданию бокса для числовых параметров.

При этом ваша проблема в том, что у вас не может быть T : decimal, double, поскольку это означает, что T должно быть и decimal и double (что невозможно), а не то, что оно можетбыть либо одним.

Кроме того, так как это все, что делает эта функция, я, вероятно, в любом случае не буду вызывать функции Math.Max и Math.Min.Вероятно, так же просто, если не чуть яснее, написать функции следующим образом:

public static decimal ClipGN(this decimal v, decimal lo, decimal hi)
{
    return v <= lo ? lo : v >= hi ? hi : v;
}

И вы сможете дублировать этот код дословно (кроме, конечно, типов возврата и параметров) длякаждый из числовых типов.

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