有人能告诉我是否有一种方法可以用泛型将泛型类型参数T限制为:
Int16 Int32 Int64 UInt16 UInt32 UInt64
我知道哪里关键字,但不能找到只有这些类型的接口,
喜欢的东西:
static bool IntegerFunction<T>(T value) where T : INumeric
有人能告诉我是否有一种方法可以用泛型将泛型类型参数T限制为:
Int16 Int32 Int64 UInt16 UInt32 UInt64
我知道哪里关键字,但不能找到只有这些类型的接口,
喜欢的东西:
static bool IntegerFunction<T>(T value) where T : INumeric
当前回答
这个练习的意义是什么?
正如人们已经指出的,你可以让一个非泛型函数取最大的项,编译器会自动为你转换较小的整型。
static bool IntegerFunction(Int64 value) { }
如果您的函数处于性能关键的路径上(在我看来,这是不太可能的),您可以为所有需要的函数提供重载。
static bool IntegerFunction(Int64 value) { }
...
static bool IntegerFunction(Int16 value) { }
其他回答
这个约束存在于。net 7中。
查看这篇。net博客文章和实际文档。
从。net 7开始,你可以使用接口如INumber和IFloatingPoint来创建程序,例如:
using System.Numerics;
Console.WriteLine(Sum(1, 2, 3, 4, 5));
Console.WriteLine(Sum(10.541, 2.645));
Console.WriteLine(Sum(1.55f, 5, 9.41f, 7));
static T Sum<T>(params T[] numbers) where T : INumber<T>
{
T result = T.Zero;
foreach (T item in numbers)
{
result += item;
}
return result;
}
innumber在系统中。数字名称空间。
还有诸如IAdditionOperators和IComparisonOperators这样的接口,因此您可以通用地使用特定的操作符。
这个问题有点像常见问题,所以我在维基上发布了这个(因为我之前发布过类似的问题,但这是一个较老的问题);无论如何……
你用的是什么版本的。net ?如果你使用的是。net 3.5,那么我在MiscUtil中有一个通用操作符实现(免费等)。
它有T Add<T>(T x, T y)等方法,以及不同类型上的其他算术变体(如DateTime + TimeSpan)。
此外,这适用于所有内置、提升和定制操作符,并缓存委托以获得性能。
这里有一些关于为什么这很棘手的额外背景。
你可能还想知道动态(4.0)也间接地解决了这个问题。
dynamic x = ..., y = ...
dynamic result = x + y; // does what you expect
不幸的是,在这种情况下,只能在where子句中指定struct。不能具体指定Int16、Int32等,这看起来确实很奇怪,但我相信,在决定不允许在where子句中使用值类型的基础上,有一些深层的实现原因。
我想唯一的解决方案是执行运行时检查,这不幸地阻止了在编译时拾取问题。大概是这样的:-
static bool IntegerFunction<T>(T value) where T : struct {
if (typeof(T) != typeof(Int16) &&
typeof(T) != typeof(Int32) &&
typeof(T) != typeof(Int64) &&
typeof(T) != typeof(UInt16) &&
typeof(T) != typeof(UInt32) &&
typeof(T) != typeof(UInt64)) {
throw new ArgumentException(
string.Format("Type '{0}' is not valid.", typeof(T).ToString()));
}
// Rest of code...
}
我知道这有点难看,但至少提供了所需的约束条件。
我还将研究此实现可能的性能影响,也许有更快的方法。
话题老了,但对未来的读者来说:
这个特性与歧视联盟紧密相关,而歧视联盟目前还没有在c#中实现。我发现它的问题在这里:
https://github.com/dotnet/csharplang/issues/113
这个问题仍然没有解决,并且已经计划在c# 10中推出新特性
所以我们仍然需要等待一段时间,但在释放之后,你可以这样做:
static bool IntegerFunction<T>(T value) where T : Int16 | Int32 | Int64 | ...
也许你能做的就是
static bool IntegerFunction<T>(T value) where T: struct
不确定你是否能做到以下几点
static bool IntegerFunction<T>(T value) where T: struct, IComparable
, IFormattable, IConvertible, IComparable<T>, IEquatable<T>
对于如此特定的内容,为什么不为每种类型设置重载呢?列表很短,而且可能占用更少的内存。