如何使用约束将T限制为值类型?

时间:2010-11-05 19:52:55

标签: c# linq generics constraints

我想使用约束来限制N可以使用的可能类型。我希望将N限制为int或decimal。

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

任何帮助表示赞赏...

6 个答案:

答案 0 :(得分:19)

无法将通用参数约束为特定值类型。

但是,您可以通过添加struct强制它 值类型或where N : struct,但这就是全部。

答案 1 :(得分:9)

不幸的是,无法指定仅允许特定值类型的泛型类型约束。更重要的是,即使它被允许也没有多大意义。

您可以将类指定为泛型约束,但这是因为您可以从类继承,因此约束设置了允许使用的类型的最小阈值。

如果允许值类型,您无法从这些类型继承,那么您实际上只能将自己限制为该类型。

因此你不能这样做,但你有几个选择:

  • 您可以在没有约束的情况下声明它,并在运行时处理问题。 我不推荐这种方式
  • 您可以声明采用您感兴趣的特定类型的重载。

    由于你只有两种这样的类型,我建议这样做。

以下是您要声明的重载:

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
}

现在,另外,如果这些值的处理并不真正依赖于这些类型的数字质量,您只想限制可以处理的类型,那么您可以随时声明原始方法,私有,并从您的重载调用此方法。这仍然会将您的代码限制为仅允许intdecimal公开,但您的实现仍然是通用的。如果不确切知道“这里的东西”是什么意思,就不可能判断这是否是一个可行的选择,但无论如何这里是代码:

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
}

答案 2 :(得分:9)

使用约束无法做到这一点。假设PopulateInto可以使用泛型N,另一种方法是使核心算法通用且私有,并提供2个公共重载,分别采用intdecimal。这将产生类似的效果

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 {
  ...
}

答案 3 :(得分:3)

正如彼得所说,你不能使用编译时检查。但是,您可以在运行时执行以下操作:

if(!(typeof(N).equals(typeof(int32))) && !(typeof(N).equals(typeof(decimal))))
  // do something

答案 4 :(得分:1)

您可以得到的壁橱是T:struct,IComparable,IFormattable,IConvertible。 所有值类型都实现这些接口。

答案 5 :(得分:1)

要在 标题 中回答问题,而不是问题的正文。

要涵盖通常由Value Types(包括Nullable Value Typesstring(即使是technically a Reference type)表示的所有类型,您需要3个重载:

public void Foo<T>(T arg) where T : struct
public void Foo<T?>(T? arg) where T : struct
public void Foo<string>(string arg)

来自MSDN Docs on generic constraints

  

where T : struct type参数必须是非空值类型。