有人能告诉我是否有一种方法可以用泛型将泛型类型参数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
当前回答
我想知道和samjudson一样,为什么只对整数有效?如果是这样的话,你可能想要创建一个helper类或者类似的东西来保存你想要的所有类型。
如果你想要的只是整数,不要使用泛型,那不是泛型;或者更好的是,通过检查其类型来拒绝任何其他类型。
其他回答
从c# 7.3开始,您可以使用更接近的非托管约束来指定类型形参是非指针、非空的非托管类型。
class SomeGeneric<T> where T : unmanaged
{
//...
}
非托管约束意味着结构约束,并且不能与结构或new()约束组合。
如果是以下类型之一,则该类型为非托管类型:
Sbyte、byte、short、ushort、int、uint、long、ulong、char、float、double、decimal或bool 任何enum类型 任何指针类型 任何只包含非托管类型字段的用户定义结构类型,在c# 7.3及更早版本中,都不是构造类型(至少包含一个类型参数的类型)。
为了进一步限制和消除没有实现IComparable的指针和用户定义类型add IComparable(但enum仍然派生自IComparable,因此通过添加IEquatable < T >来限制enum,您可以根据您的情况进一步添加额外的接口。Unmanaged可以让这个列表更短):
class SomeGeneric<T> where T : unmanaged, IComparable, IEquatable<T>
{
//...
}
但是这并没有阻止DateTime实例化。
这个约束存在于。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 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);
}
我会使用一个通用的,你可以处理外部…
/// <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;
}
我创建了一个小库功能来解决这些问题:
而不是:
public T DifficultCalculation<T>(T a, T b)
{
T result = a * b + a; // <== WILL NOT COMPILE!
return result;
}
Console.WriteLine(DifficultCalculation(2, 3)); // Should result in 8.
你可以这样写:
public T DifficultCalculation<T>(Number<T> a, Number<T> b)
{
Number<T> result = a * b + a;
return (T)result;
}
Console.WriteLine(DifficultCalculation(2, 3)); // Results in 8.
你可以在这里找到源代码:https://codereview.stackexchange.com/questions/26022/improvement-requested-for-generic-calculator-and-generic-number