谁能告诉我泛型是否有办法将泛型类型参数限制为T:
T
Int16
Int32
Int64
UInt16
UInt32
UInt64
我知道where关键字,但找不到 仅适用 于这些类型的接口,
where
就像是:
static bool IntegerFunction<T>(T value) where T : INumeric
C# 不支持这一点。Hejlsberg在接受 Bruce Eckel 的采访时描述了不实施该功能的原因:
而且还不清楚增加的复杂性是否值得您获得的少量收益。如果约束系统不直接支持你想做的事情,你可以用工厂模式来做。例如,您可能有一个Matrix<T>,并且Matrix您想在其中定义一个点积方法。这当然意味着你最终需要了解如何将两个Ts 相乘,但你不能说这是一个约束,至少不是 if Tis int, double, or float。但是你可以做的是将你的Matrix取值作为一个参数Calculator<T>,并且在Calculator<T>其中有一个名为 的方法multiply。你去实现它并将它传递给Matrix.
Matrix<T>
Matrix
int
double
float
Calculator<T>
multiply
然而,这会导致相当复杂的代码,用户必须为他们想要使用的每个提供自己的Calculator<T>实现。T只要它不是必须是可扩展的,即如果你只想支持固定数量的类型,例如intand double,你可以使用一个相对简单的接口:
var mat = new Matrix<int>(w, h);
(GitHub Gist 中的最小实现。)
但是,一旦您希望用户能够提供他们自己的自定义类型,您就需要打开此实现,以便用户可以提供他们自己的Calculator实例。例如,要实例化一个使用自定义十进制浮点实现的矩阵DFP,您必须编写以下代码:
Calculator
DFP
var mat = new Matrix<DFP>(DfpCalculator.Instance, w, h);
‘ 并执行所有成员为DfpCalculator : ICalculator<DFP>。
DfpCalculator : ICalculator<DFP>
正如所讨论的,另一种方法(不幸的是具有相同的限制)是使用策略类。 使用策略的解决方法:
interface INumericPolicy<T> { T Zero(); T Add(T a, T b); // add more functions here, such as multiplication etc. } struct NumericPolicies: INumericPolicy<int>, INumericPolicy<long> // add more INumericPolicy<> for different numeric types. { int INumericPolicy<int>.Zero() { return 0; } long INumericPolicy<long>.Zero() { return 0; } int INumericPolicy<int>.Add(int a, int b) { return a + b; } long INumericPolicy<long>.Add(long a, long b) { return a + b; } // implement all functions from INumericPolicy<> interfaces. public static NumericPolicies Instance = new NumericPolicies(); }
算法:
static class Algorithms { public static T Sum<P, T>(this P p, params T[] a) where P: INumericPolicy<T> { var r = p.Zero(); foreach(var i in a) { r = p.Add(r, i); } return r; } }
用法:
int i = NumericPolicies.Instance.Sum(1, 2, 3, 4, 5); long l = NumericPolicies.Instance.Sum(1L, 2, 3, 4, 5); NumericPolicies.Instance.Sum("www", "") // compile-time error.
该解决方案是编译时安全的。CityLizard Framework为 .NET 4.0 提供编译版本。该文件是 lib/NETFramework4.0/CityLizard.Policy.dll。
它也可以在 Nuget 中使用:https ://www.nuget.org/packages/CityLizard/ 。请参阅CityLizard.Policy.I结构。