Как ограничить T для типов значений, используя ограничение? - PullRequest
16 голосов
/ 05 ноября 2010

Я хочу ограничить возможные типы, которые N может использовать, используя ограничение.Я хочу ограничить N либо целым, либо десятичным числом.

public static Chart PopulateInto<T, N>(List<T> yAxis, List<N> xAxis) where N : int, decimal
{
    // Do stuff here
}

Любая помощь приветствуется ...

Ответы [ 5 ]

20 голосов
/ 05 ноября 2010

Невозможно ограничить универсальный параметр конкретным типом значения.

Однако вы можете сделать так, чтобы он был типом значения или struct с помощьюдобавив where N : struct, но это все.

9 голосов
/ 05 ноября 2010

Нет способа сделать это с ограничением.Однако другой подход, предполагающий, что PopulateInto может работать с общим N, состоит в том, чтобы сделать основной алгоритм algorihtm общим и частным и предлагать 2 открытые перегрузки, которые принимают int и decimal соответственно.Это создаст подобный эффект

public static Chart PopulateInto<T>(
  List<T> yAxis, 
  List<decimal> xAxis) {

  return PopulateIntoCore(yAxis, xAxis);
}

public static Chart PopulateInto<T>(
  List<T> yAxis, 
  List<int> xAxis) {

  return PopulateIntoCore(yAxis, xAxis);
}

private static Chart PopulateIntoCore<T, N>(
  List<T> yAxis, 
  List<N> xAxis) where N : struct {
  ...
}
9 голосов
/ 05 ноября 2010

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

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

Если бы это было разрешено для типов значений, где вы не можете наследовать от этих типов, вы бы эффективно ограничивали себя только этим типом.

Таким образом, вы не можете сделать это, но у вас есть несколько альтернатив:

  • Вы можете объявить это без ограничений и решить проблему во время выполнения. Я бы не рекомендовал этот способ
  • Вы можете объявить перегрузки, которые принимают определенные типы, которые вас интересуют.

    Поскольку у вас есть только два таких типа, этоэто то, что я бы рекомендовал сделать.

Вот перегрузки, которые вы бы объявили:

public static Chart PopulateInto<T>(List<T> yAxis, List<int> xAxis)
{
    // Do stuff here
}

public static Chart PopulateInto<T>(List<T> yAxis, List<decimal> xAxis)
{
    // Do stuff here
}

Теперь, дополнительно, если ваша обработка из этих значений на самом деле не зависят от числового качества этих типов, вы просто хотите ограничить, какие типы вы можете обрабатывать, тогда вы всегда можете объявить свой оригинальный метод, конфиденциально и вызватьэтот метод от ваших перегрузок.Это по-прежнему ограничивает ваш код только разрешением int или decimal, публично , но ваша реализация все равно будет общей.Не зная точно, что влечет за собой «Делать что-то здесь», невозможно сказать, является ли это приемлемым вариантом или нет, но вот код в любом случае:

public static Chart PopulateInto<T>(List<T> yAxis, List<int> xAxis)
{
    return PopulateInto<T, int>(yAxis, xAxis);
}

public static Chart PopulateInto<T>(List<T> yAxis, List<decimal> xAxis)
{
    return PopulateInto<T, decimal>(yAxis, xAxis);
}

private static Chart PopulateInto<T, N>(List<T> yAxis, List<N> xAxis) where N : struct
{
    // Do stuff here
}
3 голосов
/ 05 ноября 2010

Как сказал Питер, вы не можете использовать проверку времени компиляции для этого.Однако вы можете сделать следующее во время выполнения:

if(!(typeof(N).equals(typeof(int32))) && !(typeof(N).equals(typeof(decimal))))
  // do something
1 голос
/ 04 мая 2019

Шкаф, который вы можете получить: Где T: структура, IComparable, IFormattable, IConvertible. Все типы значений реализуют эти интерфейсы.

...