有人能告诉我是否有一种方法可以用泛型将泛型类型参数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
当前回答
目前还没有“好的”解决方案。但是,您可以显著地缩小类型参数,以排除许多与您假设的“INumeric”约束不匹配的情况,如上面haacks所示。
static bool IntegerFunction<T>(T值)where T: IComparable, iformatable, IConvertible, IComparable<T>, IEquatable<T>, struct {…
其他回答
.NET 6有一个预览功能:
https://devblogs.microsoft.com/dotnet/preview-features-in-net-6-generic-math/#generic-math
下面是文章中的一个例子:
static T Add<T>(T left, T right)
where T : INumber<T>
{
return left + right;
}
INumber是一个实现其他接口的接口,比如IAdditionOperators,它允许通用的+用法。现在这是可能的,因为另一个预览特性是接口中的静态抽象,因为+操作符重载是一个静态方法:
/// <summary>Defines a mechanism for computing the sum of two values.</summary>
/// <typeparam name="TSelf">The type that implements this interface.</typeparam>
/// <typeparam name="TOther">The type that will be added to <typeparamref name="TSelf" />.</typeparam>
/// <typeparam name="TResult">The type that contains the sum of <typeparamref name="TSelf" /> and <typeparamref name="TOther" />.</typeparam>
[RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)]
public interface IAdditionOperators<TSelf, TOther, TResult>
where TSelf : IAdditionOperators<TSelf, TOther, TResult>
{
/// <summary>Adds two values together to compute their sum.</summary>
/// <param name="left">The value to which <paramref name="right" /> is added.</param>
/// <param name="right">The value which is added to <paramref name="left" />.</param>
/// <returns>The sum of <paramref name="left" /> and <paramref name="right" />.</returns>
static abstract TResult operator +(TSelf left, TOther right);
}
这个练习的意义是什么?
正如人们已经指出的,你可以让一个非泛型函数取最大的项,编译器会自动为你转换较小的整型。
static bool IntegerFunction(Int64 value) { }
如果您的函数处于性能关键的路径上(在我看来,这是不太可能的),您可以为所有需要的函数提供重载。
static bool IntegerFunction(Int64 value) { }
...
static bool IntegerFunction(Int16 value) { }
这是没有限制的。对于任何想要使用泛型进行数值计算的人来说,这都是一个真正的问题。
更进一步说,我们需要
static bool GenericFunction<T>(T value)
where T : operators( +, -, /, * )
甚至
static bool GenericFunction<T>(T value)
where T : Add, Subtract
不幸的是,你只有接口,基类和关键字struct(必须是值类型),class(必须是引用类型)和new()(必须有默认构造函数)
你可以把数字包装在其他东西(类似于INullable<T>),就像这里的codeproject。
您可以在运行时应用该限制(通过对操作符进行反射或检查类型),但这首先就失去了使用泛型的优势。
使用策略的解决方案:
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框架提供了。net 4.0的编译版本。文件名为“lib/NETFramework4.0/ citylizad . policy .dll”。
它也可以在Nuget: https://www.nuget.org/packages/CityLizard/。参见CityLizard.Policy.I结构。
我会使用一个通用的,你可以处理外部…
/// <summary>
/// Generic object copy of the same type
/// </summary>
/// <typeparam name="T">The type of object to copy</typeparam>
/// <param name="ObjectSource">The source object to copy</param>
public T CopyObject<T>(T ObjectSource)
{
T NewObject = System.Activator.CreateInstance<T>();
foreach (PropertyInfo p in ObjectSource.GetType().GetProperties())
NewObject.GetType().GetProperty(p.Name).SetValue(NewObject, p.GetValue(ObjectSource, null), null);
return NewObject;
}