如何使用约束将 T 限制为值类型?
Posted
技术标签:
【中文标题】如何使用约束将 T 限制为值类型?【英文标题】:How to restrict T to value types using a constraint? 【发布时间】: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 次重载,但这还不错。 【参考方案1】:不能将泛型参数限制为特定的值类型。
但是,您可以通过添加 where N : struct
将其强制为 a 值类型或 struct
,仅此而已。
【讨论】:
另一种处理方法是为int
或 decimal
列表设置特定的重载。【参考方案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
现在,另外,如果您对这些值的处理并不真正依赖于这些类型的数值质量,您只想限制可以处理的类型,那么您可以随时声明您的原始方法,私下,并从您的重载中调用此方法。这仍然会将您的代码限制为只允许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
【讨论】:
我的泛型已关闭,这就是我在周五晚上写答案时得到的,让我更正一下。 感谢您的建设性批评。不幸的是,标题中的问题具有误导性,因为如果我们将自己限制在这个范围内,那么答案很简单:where N : struct
。然而,真正的问题只有一个真实的、确定的答案,那就是“这在当前允许的 C# 语法中是不可能的”。不过,我已经扩展了我的答案以涵盖所有选项,希望它会浪费更少的时间。【参考方案3】:
没有办法通过约束来做到这一点。不过,另一种方法是,假设PopulateInto
可以与通用 N 一起工作,是使核心算法通用和私有,并提供 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
...
【讨论】:
@Mark,是的,这将是我回答的关键;)已修复【参考方案4】:正如 Pieter 所说,您不能对此使用编译时检查。但是,您可以在运行时执行以下操作:
if(!(typeof(N).equals(typeof(int32))) && !(typeof(N).equals(typeof(decimal))))
// do something
【讨论】:
是的,为什么不呢。抛出 InvalidOperationException。【参考方案5】:回答标题中的问题,而不是问题的正文。
要涵盖Value Types
(包括Nullable Value Types 和string
,即使它是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。 所有值类型都实现了这些接口。
【讨论】:
以上是关于如何使用约束将 T 限制为值类型?的主要内容,如果未能解决你的问题,请参考以下文章