【问题标题】:How to restrict T to value types using a constraint?如何使用约束将 T 限制为值类型?
【发布时间】:2010-11-05 19:52:55
【问题描述】:

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

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

任何帮助表示赞赏...

【问题讨论】:

  • 如果您只关心这两种类型,我认为您可以重载该方法。当然是 4 次重载,但这还不错。

标签: c# linq generics constraints


【解决方案1】:

不能将泛型参数限制为特定的值类型。

但是,您可以通过添加 where N : struct 将其强制为 a 值类型或 struct,仅此而已。

【讨论】:

  • 另一种处理方法是为 intdecimal 列表设置特定的重载。
【解决方案2】:

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

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

如果值类型允许这样做,而您不能从这些类型继承,那么您实际上会将自己限制为仅使用该类型。

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

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

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

这里是你要声明的重载:

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
}

【讨论】:

  • 我的泛型已关闭,这就是我在周五晚上写答案时得到的,让我更正一下。
  • 感谢您的建设性批评。不幸的是,标题中的问题具有误导性,因为如果我们将自己限制在这个范围内,那么答案很简单:where N : struct。然而,真正的问题只有一个真实的、确定的答案,那就是“这在当前允许的 C# 语法中是不可能的”。不过,我已经扩展了我的答案以涵盖所有选项,希望它会浪费更少的时间。
【解决方案3】:

没有办法通过约束来做到这一点。不过,另一种方法是,假设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 {
  ...
}

【讨论】:

  • @Mark,是的,这将是我回答的关键;)已修复
【解决方案4】:

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

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

【讨论】:

  • 是的,为什么不呢。抛出 InvalidOperationException。
【解决方案5】:

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

要涵盖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 参数必须是不可为空的值类型。

【讨论】:

    【解决方案6】:

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

    【讨论】:

      猜你喜欢
      • 2011-06-12
      • 2017-01-21
      • 1970-01-01
      • 1970-01-01
      • 2015-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-10
      相关资源
      最近更新 更多