有人能告诉我是否有一种方法可以用泛型将泛型类型参数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
当前回答
如果你使用的是。net 4.0或更高版本,那么你可以使用dynamic作为方法参数,并在运行时检查传递的动态参数类型是数字/整数类型。
如果传递的动态类型不是数字/整数类型,则抛出异常。
实现这一想法的简短代码示例如下:
using System;
public class InvalidArgumentException : Exception
{
public InvalidArgumentException(string message) : base(message) {}
}
public class InvalidArgumentTypeException : InvalidArgumentException
{
public InvalidArgumentTypeException(string message) : base(message) {}
}
public class ArgumentTypeNotIntegerException : InvalidArgumentTypeException
{
public ArgumentTypeNotIntegerException(string message) : base(message) {}
}
public static class Program
{
private static bool IntegerFunction(dynamic n)
{
if (n.GetType() != typeof(Int16) &&
n.GetType() != typeof(Int32) &&
n.GetType() != typeof(Int64) &&
n.GetType() != typeof(UInt16) &&
n.GetType() != typeof(UInt32) &&
n.GetType() != typeof(UInt64))
throw new ArgumentTypeNotIntegerException("argument type is not integer type");
//code that implements IntegerFunction goes here
}
private static void Main()
{
Console.WriteLine("{0}",IntegerFunction(0)); //Compiles, no run time error and first line of output buffer is either "True" or "False" depends on the code that implements "Program.IntegerFunction" static method.
Console.WriteLine("{0}",IntegerFunction("string")); //Also compiles but it is run time error and exception of type "ArgumentTypeNotIntegerException" is thrown here.
Console.WriteLine("This is the last Console.WriteLine output"); //Never reached and executed due the run time error and the exception thrown on the second line of Program.Main static method.
}
当然,这个解决方案只能在运行时工作,而不能在编译时工作。
如果你想要一个总是在编译时工作而不在运行时工作的解决方案,那么你必须用一个公共结构/类来包装动态,它的重载公共构造函数只接受所需类型的参数,并给结构/类适当的名称。
被包装的动态总是类/结构的私有成员,它是结构/类的唯一成员,结构/类的唯一成员的名字是“value”,这是有意义的。
如果需要,还必须定义和实现公共方法和/或操作符,这些方法和/或操作符用于类/结构的私有动态成员的所需类型。
同样有意义的是,结构/类有特殊的/唯一的构造函数,它接受dynamic作为参数,初始化它唯一的私有动态成员“value”,但这个构造函数的修饰符当然是私有的。
类/结构准备好后,将参数的IntegerFunction类型定义为已定义的类/结构。
实现这个想法的长代码示例如下:
using System;
public struct Integer
{
private dynamic value;
private Integer(dynamic n) { this.value = n; }
public Integer(Int16 n) { this.value = n; }
public Integer(Int32 n) { this.value = n; }
public Integer(Int64 n) { this.value = n; }
public Integer(UInt16 n) { this.value = n; }
public Integer(UInt32 n) { this.value = n; }
public Integer(UInt64 n) { this.value = n; }
public Integer(Integer n) { this.value = n.value; }
public static implicit operator Int16(Integer n) { return n.value; }
public static implicit operator Int32(Integer n) { return n.value; }
public static implicit operator Int64(Integer n) { return n.value; }
public static implicit operator UInt16(Integer n) { return n.value; }
public static implicit operator UInt32(Integer n) { return n.value; }
public static implicit operator UInt64(Integer n) { return n.value; }
public static Integer operator +(Integer x, Int16 y) { return new Integer(x.value + y); }
public static Integer operator +(Integer x, Int32 y) { return new Integer(x.value + y); }
public static Integer operator +(Integer x, Int64 y) { return new Integer(x.value + y); }
public static Integer operator +(Integer x, UInt16 y) { return new Integer(x.value + y); }
public static Integer operator +(Integer x, UInt32 y) { return new Integer(x.value + y); }
public static Integer operator +(Integer x, UInt64 y) { return new Integer(x.value + y); }
public static Integer operator -(Integer x, Int16 y) { return new Integer(x.value - y); }
public static Integer operator -(Integer x, Int32 y) { return new Integer(x.value - y); }
public static Integer operator -(Integer x, Int64 y) { return new Integer(x.value - y); }
public static Integer operator -(Integer x, UInt16 y) { return new Integer(x.value - y); }
public static Integer operator -(Integer x, UInt32 y) { return new Integer(x.value - y); }
public static Integer operator -(Integer x, UInt64 y) { return new Integer(x.value - y); }
public static Integer operator *(Integer x, Int16 y) { return new Integer(x.value * y); }
public static Integer operator *(Integer x, Int32 y) { return new Integer(x.value * y); }
public static Integer operator *(Integer x, Int64 y) { return new Integer(x.value * y); }
public static Integer operator *(Integer x, UInt16 y) { return new Integer(x.value * y); }
public static Integer operator *(Integer x, UInt32 y) { return new Integer(x.value * y); }
public static Integer operator *(Integer x, UInt64 y) { return new Integer(x.value * y); }
public static Integer operator /(Integer x, Int16 y) { return new Integer(x.value / y); }
public static Integer operator /(Integer x, Int32 y) { return new Integer(x.value / y); }
public static Integer operator /(Integer x, Int64 y) { return new Integer(x.value / y); }
public static Integer operator /(Integer x, UInt16 y) { return new Integer(x.value / y); }
public static Integer operator /(Integer x, UInt32 y) { return new Integer(x.value / y); }
public static Integer operator /(Integer x, UInt64 y) { return new Integer(x.value / y); }
public static Integer operator %(Integer x, Int16 y) { return new Integer(x.value % y); }
public static Integer operator %(Integer x, Int32 y) { return new Integer(x.value % y); }
public static Integer operator %(Integer x, Int64 y) { return new Integer(x.value % y); }
public static Integer operator %(Integer x, UInt16 y) { return new Integer(x.value % y); }
public static Integer operator %(Integer x, UInt32 y) { return new Integer(x.value % y); }
public static Integer operator %(Integer x, UInt64 y) { return new Integer(x.value % y); }
public static Integer operator +(Integer x, Integer y) { return new Integer(x.value + y.value); }
public static Integer operator -(Integer x, Integer y) { return new Integer(x.value - y.value); }
public static Integer operator *(Integer x, Integer y) { return new Integer(x.value * y.value); }
public static Integer operator /(Integer x, Integer y) { return new Integer(x.value / y.value); }
public static Integer operator %(Integer x, Integer y) { return new Integer(x.value % y.value); }
public static bool operator ==(Integer x, Int16 y) { return x.value == y; }
public static bool operator !=(Integer x, Int16 y) { return x.value != y; }
public static bool operator ==(Integer x, Int32 y) { return x.value == y; }
public static bool operator !=(Integer x, Int32 y) { return x.value != y; }
public static bool operator ==(Integer x, Int64 y) { return x.value == y; }
public static bool operator !=(Integer x, Int64 y) { return x.value != y; }
public static bool operator ==(Integer x, UInt16 y) { return x.value == y; }
public static bool operator !=(Integer x, UInt16 y) { return x.value != y; }
public static bool operator ==(Integer x, UInt32 y) { return x.value == y; }
public static bool operator !=(Integer x, UInt32 y) { return x.value != y; }
public static bool operator ==(Integer x, UInt64 y) { return x.value == y; }
public static bool operator !=(Integer x, UInt64 y) { return x.value != y; }
public static bool operator ==(Integer x, Integer y) { return x.value == y.value; }
public static bool operator !=(Integer x, Integer y) { return x.value != y.value; }
public override bool Equals(object obj) { return this == (Integer)obj; }
public override int GetHashCode() { return this.value.GetHashCode(); }
public override string ToString() { return this.value.ToString(); }
public static bool operator >(Integer x, Int16 y) { return x.value > y; }
public static bool operator <(Integer x, Int16 y) { return x.value < y; }
public static bool operator >(Integer x, Int32 y) { return x.value > y; }
public static bool operator <(Integer x, Int32 y) { return x.value < y; }
public static bool operator >(Integer x, Int64 y) { return x.value > y; }
public static bool operator <(Integer x, Int64 y) { return x.value < y; }
public static bool operator >(Integer x, UInt16 y) { return x.value > y; }
public static bool operator <(Integer x, UInt16 y) { return x.value < y; }
public static bool operator >(Integer x, UInt32 y) { return x.value > y; }
public static bool operator <(Integer x, UInt32 y) { return x.value < y; }
public static bool operator >(Integer x, UInt64 y) { return x.value > y; }
public static bool operator <(Integer x, UInt64 y) { return x.value < y; }
public static bool operator >(Integer x, Integer y) { return x.value > y.value; }
public static bool operator <(Integer x, Integer y) { return x.value < y.value; }
public static bool operator >=(Integer x, Int16 y) { return x.value >= y; }
public static bool operator <=(Integer x, Int16 y) { return x.value <= y; }
public static bool operator >=(Integer x, Int32 y) { return x.value >= y; }
public static bool operator <=(Integer x, Int32 y) { return x.value <= y; }
public static bool operator >=(Integer x, Int64 y) { return x.value >= y; }
public static bool operator <=(Integer x, Int64 y) { return x.value <= y; }
public static bool operator >=(Integer x, UInt16 y) { return x.value >= y; }
public static bool operator <=(Integer x, UInt16 y) { return x.value <= y; }
public static bool operator >=(Integer x, UInt32 y) { return x.value >= y; }
public static bool operator <=(Integer x, UInt32 y) { return x.value <= y; }
public static bool operator >=(Integer x, UInt64 y) { return x.value >= y; }
public static bool operator <=(Integer x, UInt64 y) { return x.value <= y; }
public static bool operator >=(Integer x, Integer y) { return x.value >= y.value; }
public static bool operator <=(Integer x, Integer y) { return x.value <= y.value; }
public static Integer operator +(Int16 x, Integer y) { return new Integer(x + y.value); }
public static Integer operator +(Int32 x, Integer y) { return new Integer(x + y.value); }
public static Integer operator +(Int64 x, Integer y) { return new Integer(x + y.value); }
public static Integer operator +(UInt16 x, Integer y) { return new Integer(x + y.value); }
public static Integer operator +(UInt32 x, Integer y) { return new Integer(x + y.value); }
public static Integer operator +(UInt64 x, Integer y) { return new Integer(x + y.value); }
public static Integer operator -(Int16 x, Integer y) { return new Integer(x - y.value); }
public static Integer operator -(Int32 x, Integer y) { return new Integer(x - y.value); }
public static Integer operator -(Int64 x, Integer y) { return new Integer(x - y.value); }
public static Integer operator -(UInt16 x, Integer y) { return new Integer(x - y.value); }
public static Integer operator -(UInt32 x, Integer y) { return new Integer(x - y.value); }
public static Integer operator -(UInt64 x, Integer y) { return new Integer(x - y.value); }
public static Integer operator *(Int16 x, Integer y) { return new Integer(x * y.value); }
public static Integer operator *(Int32 x, Integer y) { return new Integer(x * y.value); }
public static Integer operator *(Int64 x, Integer y) { return new Integer(x * y.value); }
public static Integer operator *(UInt16 x, Integer y) { return new Integer(x * y.value); }
public static Integer operator *(UInt32 x, Integer y) { return new Integer(x * y.value); }
public static Integer operator *(UInt64 x, Integer y) { return new Integer(x * y.value); }
public static Integer operator /(Int16 x, Integer y) { return new Integer(x / y.value); }
public static Integer operator /(Int32 x, Integer y) { return new Integer(x / y.value); }
public static Integer operator /(Int64 x, Integer y) { return new Integer(x / y.value); }
public static Integer operator /(UInt16 x, Integer y) { return new Integer(x / y.value); }
public static Integer operator /(UInt32 x, Integer y) { return new Integer(x / y.value); }
public static Integer operator /(UInt64 x, Integer y) { return new Integer(x / y.value); }
public static Integer operator %(Int16 x, Integer y) { return new Integer(x % y.value); }
public static Integer operator %(Int32 x, Integer y) { return new Integer(x % y.value); }
public static Integer operator %(Int64 x, Integer y) { return new Integer(x % y.value); }
public static Integer operator %(UInt16 x, Integer y) { return new Integer(x % y.value); }
public static Integer operator %(UInt32 x, Integer y) { return new Integer(x % y.value); }
public static Integer operator %(UInt64 x, Integer y) { return new Integer(x % y.value); }
public static bool operator ==(Int16 x, Integer y) { return x == y.value; }
public static bool operator !=(Int16 x, Integer y) { return x != y.value; }
public static bool operator ==(Int32 x, Integer y) { return x == y.value; }
public static bool operator !=(Int32 x, Integer y) { return x != y.value; }
public static bool operator ==(Int64 x, Integer y) { return x == y.value; }
public static bool operator !=(Int64 x, Integer y) { return x != y.value; }
public static bool operator ==(UInt16 x, Integer y) { return x == y.value; }
public static bool operator !=(UInt16 x, Integer y) { return x != y.value; }
public static bool operator ==(UInt32 x, Integer y) { return x == y.value; }
public static bool operator !=(UInt32 x, Integer y) { return x != y.value; }
public static bool operator ==(UInt64 x, Integer y) { return x == y.value; }
public static bool operator !=(UInt64 x, Integer y) { return x != y.value; }
public static bool operator >(Int16 x, Integer y) { return x > y.value; }
public static bool operator <(Int16 x, Integer y) { return x < y.value; }
public static bool operator >(Int32 x, Integer y) { return x > y.value; }
public static bool operator <(Int32 x, Integer y) { return x < y.value; }
public static bool operator >(Int64 x, Integer y) { return x > y.value; }
public static bool operator <(Int64 x, Integer y) { return x < y.value; }
public static bool operator >(UInt16 x, Integer y) { return x > y.value; }
public static bool operator <(UInt16 x, Integer y) { return x < y.value; }
public static bool operator >(UInt32 x, Integer y) { return x > y.value; }
public static bool operator <(UInt32 x, Integer y) { return x < y.value; }
public static bool operator >(UInt64 x, Integer y) { return x > y.value; }
public static bool operator <(UInt64 x, Integer y) { return x < y.value; }
public static bool operator >=(Int16 x, Integer y) { return x >= y.value; }
public static bool operator <=(Int16 x, Integer y) { return x <= y.value; }
public static bool operator >=(Int32 x, Integer y) { return x >= y.value; }
public static bool operator <=(Int32 x, Integer y) { return x <= y.value; }
public static bool operator >=(Int64 x, Integer y) { return x >= y.value; }
public static bool operator <=(Int64 x, Integer y) { return x <= y.value; }
public static bool operator >=(UInt16 x, Integer y) { return x >= y.value; }
public static bool operator <=(UInt16 x, Integer y) { return x <= y.value; }
public static bool operator >=(UInt32 x, Integer y) { return x >= y.value; }
public static bool operator <=(UInt32 x, Integer y) { return x <= y.value; }
public static bool operator >=(UInt64 x, Integer y) { return x >= y.value; }
public static bool operator <=(UInt64 x, Integer y) { return x <= y.value; }
}
public static class Program
{
private static bool IntegerFunction(Integer n)
{
//code that implements IntegerFunction goes here
//note that there is NO code that checks the type of n in rum time, because it is NOT needed anymore
}
private static void Main()
{
Console.WriteLine("{0}",IntegerFunction(0)); //compile error: there is no overloaded METHOD for objects of type "int" and no implicit conversion from any object, including "int", to "Integer" is known.
Console.WriteLine("{0}",IntegerFunction(new Integer(0))); //both compiles and no run time error
Console.WriteLine("{0}",IntegerFunction("string")); //compile error: there is no overloaded METHOD for objects of type "string" and no implicit conversion from any object, including "string", to "Integer" is known.
Console.WriteLine("{0}",IntegerFunction(new Integer("string"))); //compile error: there is no overloaded CONSTRUCTOR for objects of type "string"
}
}
注意,为了在你的代码中使用动态,你必须添加引用到微软。CSharp
如果. net框架的版本低于/低于/小于4.0,并且动态在该版本中未定义,那么你将不得不使用对象来代替,并将其转换为整数类型,这很麻烦,所以我建议你至少使用。net 4.0或更新版本,如果可以的话,这样你就可以使用动态而不是对象。
其他回答
当我试图重载泛型类型的操作符时,这个限制影响了我;由于没有“innumeric”约束,以及stackoverflow上的优秀人员乐于提供的一系列其他原因,操作不能在泛型类型上定义。
我想要的是
public struct Foo<T>
{
public T Value{ get; private set; }
public static Foo<T> operator +(Foo<T> LHS, Foo<T> RHS)
{
return new Foo<T> { Value = LHS.Value + RHS.Value; };
}
}
我已经使用。net4动态运行时类型解决了这个问题。
public struct Foo<T>
{
public T Value { get; private set; }
public static Foo<T> operator +(Foo<T> LHS, Foo<T> RHS)
{
return new Foo<T> { Value = LHS.Value + (dynamic)RHS.Value };
}
}
关于使用动态的两件事是
的性能。所有值类型都被装箱。 运行时错误。你“打败”了编译器,但失去了类型安全。如果泛型类型没有定义操作符,则会在执行期间抛出异常。
没有办法将模板限制为类型,但是可以根据类型定义不同的操作。作为泛型数值包的一部分,我需要一个泛型类来添加两个值。
class Something<TCell>
{
internal static TCell Sum(TCell first, TCell second)
{
if (typeof(TCell) == typeof(int))
return (TCell)((object)(((int)((object)first)) + ((int)((object)second))));
if (typeof(TCell) == typeof(double))
return (TCell)((object)(((double)((object)first)) + ((double)((object)second))));
return second;
}
}
请注意,typeofs是在编译时计算的,因此if语句将被编译器删除。编译器还会删除虚假的类型转换。因此,在编译器中会解析为
internal static int Sum(int first, int second)
{
return first + second;
}
我想知道和samjudson一样,为什么只对整数有效?如果是这样的话,你可能想要创建一个helper类或者类似的东西来保存你想要的所有类型。
如果你想要的只是整数,不要使用泛型,那不是泛型;或者更好的是,通过检查其类型来拒绝任何其他类型。
我会使用一个通用的,你可以处理外部…
/// <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;
}
这个练习的意义是什么?
正如人们已经指出的,你可以让一个非泛型函数取最大的项,编译器会自动为你转换较小的整型。
static bool IntegerFunction(Int64 value) { }
如果您的函数处于性能关键的路径上(在我看来,这是不太可能的),您可以为所有需要的函数提供重载。
static bool IntegerFunction(Int64 value) { }
...
static bool IntegerFunction(Int16 value) { }