谁能告诉我,如果有泛型办法泛型类型参数T
仅限制于:是否有一个约束将我的泛型方法限制为数字类型?
Int16
Int32
Int64
UInt16
UInt32
UInt64
我知道了where
关键字,但找不到仅这些类型的接口,
喜欢的东西:
static bool IntegerFunction<T>(T value) where T : INumeric
谁能告诉我,如果有泛型办法泛型类型参数T
仅限制于:是否有一个约束将我的泛型方法限制为数字类型?
Int16
Int32
Int64
UInt16
UInt32
UInt64
我知道了where
关键字,但找不到仅这些类型的接口,
喜欢的东西:
static bool IntegerFunction<T>(T value) where T : INumeric
Hejlsberg描述了为何不与布鲁斯·埃克尔实现该特性in an interview。
不过,我不得不承认,我不知道他是如何认为他提出的解决方法可行的。他的提议是将算术运算推迟到其他一些通用类(阅读面试!)。这有什么帮助?恕我直言,不是很多。
没有单一的接口或基类他们都继承(这不是也由其他类继承),所以简单的答案是否定的。
我想知道为什么这是一个问题。你想在你的IntegerFunction类中做什么,只能做到整数?
对此没有限制。对于任何想要使用泛型进行数字计算的人来说,这是一个真正的问题。
我会进一步说,我们需要
static bool GenericFunction<T>(T value)
where T : operators(+, -, /, *)
甚至
static bool GenericFunction<T>(T value)
where T : Add, Subtract
不幸的是你只有接口,基类和关键字struct
(必须是数值型),class
(必须是引用类型)和new()
(必须具有默认构造函数)
您可以将该数字包装在其他类似内容中(类似到INullable<T>
),如here on codeproject。
您可以在运行时应用限制(通过反映操作符或检查类型),但确实失去了将泛型放在首位的好处。
也许你可以做的最接近的是
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>
这么具体的事情,为什么不只是重载每种类型的列表这么短,它可能会有更少的内存占用。
我想知道和samjudson一样,为什么只有整数?如果是这样的话,你可能想创建一个辅助类或类似的东西来保存你想要的所有类型。
如果你想要的只是整数,不要使用通用的,这不是通用的;或者更好,通过检查其类型来拒绝任何其他类型。
不幸的是,你只能在这个实例的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...
}
这是有点难看我知道,但至少提供了所需的约束。
我也想看看这个实现可能的性能影响,也许有更快的方法。
我想你是误解了泛型。如果您试图执行的操作仅适用于特定的数据类型,那么您不会执行“通用”操作。
此外,由于您只是想允许该函数在int数据类型上工作,因此您不应该为每个特定大小需要单独的函数。只需在最大特定类型中使用参数,程序就可以自动将更小的数据类型上传到它。 (即在调用时传递Int16将自动转换为Int64)。
如果你正在执行基于被传入函数的int的实际大小的不同操作,那么我认为你应该认真地重新考虑甚至试图做你正在做的事情。如果你不得不愚弄语言,你应该更多地考虑你想要完成的事情,而不是如何去做你想做的事情。
如果失败,可以使用Object类型的参数,然后您必须检查参数的类型并采取适当的操作或抛出异常。
考虑一个类直方图
练习的要点是什么?
正如人们已经指出的那样,您可以拥有一个非泛型函数来获取最大的项目,编译器会自动为您转换更小的整数。
static bool IntegerFunction(Int64 value) { }
如果你的功能是对性能关键路径(不太可能,IMO),你可以提供所有需要的功能重载。
static bool IntegerFunction(Int64 value) { }
...
static bool IntegerFunction(Int16 value) { }
这个问题是一个常见问题之一,所以我发布这个wiki作为维基(因为我以前发布类似,但这是一个较旧的);无论如何...
您使用的是什么版本的.NET?如果您使用的是.NET 3.5,那么我的(免费等)有generic operators implementation。
这有像T Add<T>(T x, T y)
和其他变种算法在不同类型(如DateTime + TimeSpan
)的方法。
此外,这适用于所有内置,解除和定制的操作员,并缓存代表性能。
为什么这是棘手的一些额外的背景是here。
你可能也想知道,dynamic
(4.0)进行排序,解决了这个问题,也间接地 - 即
dynamic x = ..., y = ...
dynamic result = x + y; // does what you expect
我会用一个通用的一个,你可以externaly处理...
/// <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;
}
当我尝试为泛型类型重载运算符时,此限制会影响到我;由于没有“INumeric”约束,并且出于其他原因,堆栈中的好人很乐意提供,操作无法在泛型上定义。
我想要的东西像
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 };
}
}
有关使用dynamic
这两件东西
使用变通方法策略:
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结构。
这还没有“好”的解决方案。然而,你可以显着地缩小类型参数,以排除许多适合你的假设的'INumeric'约束的缺陷,正如Haacked上面所示。
静态布尔IntegerFunction <Ť>(T值)其中,T:IComparable的,IFormattable,IConvertible,IComparable的<Ť>,IEquatable <Ť>,结构 {...
的.NET数字基本类型不共享任何通用的接口,使他们被用于计算。这将有可能定义自己的接口(例如ISignedWholeNumber
),这将执行这样的操作,定义包含一个Int16
,Int32
等结构和实现这些接口,然后具有接受泛型类型约束到ISignedWholeNumber
方法,但有将数值转换为您的结构类型可能会造成滋扰。
另一种方法是定义静态类Int64Converter<T>
与静态属性bool Available {get;};
和静态代表为Int64 GetInt64(T value)
,T FromInt64(Int64 value)
,bool TryStoreInt64(Int64 value, ref T dest)
。类构造函数可以使用硬编码来加载代表了已知类型的,并且可能使用反射来测试类型T
是否实现用正确的名称和签名的方法(如果它的东西,就像它包含一个Int64
和代表数字的一个结构,但有一个自定义的ToString()
方法)。这种方法将失去与编译时类型检查相关的优点,但仍然可以避免装箱操作,并且每种类型只需要“检查”一次。之后,与该类型相关的操作将替换为委托调度。
我创建了一个小图书馆功能来解决这些问题:
相反的:
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.
考虑到这个问题的普及和对这样的功能背后的兴趣我很惊讶地发现没有涉及T4的答案。
在此示例代码中,我将展示你如何使用强大的模板引擎做的编译器几乎不与仿制药的幕后一个很简单的例子。
而是通过篮球去和牺牲编译时的确定性,你可以简单地生成每一个你喜欢的类型和使用你想要的功能是否发生相应(在编译时!)。
为了做到这一点:
<#@ template language="C#" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Core" #>
<# Type[] types = new[] {
typeof(Int16), typeof(Int32), typeof(Int64),
typeof(UInt16), typeof(UInt32), typeof(UInt64)
};
#>
using System;
public static class MaxMath {
<# foreach (var type in types) {
#>
public static <#= type.Name #> Max (<#= type.Name #> val1, <#= type.Name #> val2) {
return val1 > val2 ? val1 : val2;
}
<#
} #>
}
就是这样。你现在完成了。
保存此文件将自动编译这个源文件:
using System;
public static class MaxMath {
public static Int16 Max (Int16 val1, Int16 val2) {
return val1 > val2 ? val1 : val2;
}
public static Int32 Max (Int32 val1, Int32 val2) {
return val1 > val2 ? val1 : val2;
}
public static Int64 Max (Int64 val1, Int64 val2) {
return val1 > val2 ? val1 : val2;
}
public static UInt16 Max (UInt16 val1, UInt16 val2) {
return val1 > val2 ? val1 : val2;
}
public static UInt32 Max (UInt32 val1, UInt32 val2) {
return val1 > val2 ? val1 : val2;
}
public static UInt64 Max (UInt64 val1, UInt64 val2) {
return val1 > val2 ? val1 : val2;
}
}
在你main
方法,你可以验证是否有编译时肯定:
namespace TTTTTest
{
class Program
{
static void Main(string[] args)
{
long val1 = 5L;
long val2 = 10L;
Console.WriteLine(MaxMath.Max(val1, val2));
Console.Read();
}
}
}
我会提前一条评论:不,这不违反DRY原则。 DRY原则是为了防止人们在多个地方复制代码,这会导致应用程序难以维护。
在这里并非如此:如果您想要更改,那么您可以更改模板(为您的所有人提供单一源代码!)并完成。
为了将它与您自己的自定义定义一起使用,请向生成的代码中添加一个名称空间声明(确保它与您定义自己的实现的声明相同)并将该类标记为partial
。然后,这些行添加到您的模板文件,所以它会被包含在最终编译:
<#@ import namespace="TheNameSpaceYouWillUse" #>
<#@ assembly name="$(TargetPath)" #>
坦率地说:这是很酷。
免责声明:本示例受Metaprogramming in .NET by Kevin Hazzard and Jason Bock, Manning Publications严重影响。
无法将模板限制为类型,但可以根据类型定义不同的操作。作为泛型数值包的一部分,我需要一个泛型类来添加两个值。
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;
}
如果您使用的是.NET 4.0及更高版本,那么你可以只使用动态作为方法参数,检查在运行时,传递的动态参数类型数字/整数类型。
如果通过动态的类型是不数字 /整数类型则抛出异常。实现这个想法
一个例子短代码是一样的东西:
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.
}
当然,这种解决方案在工作运行时只,但从来没有在编译的时候。
如果你想一个解决方案,始终工作在编译的时候,从来没有在运行时,那么你将有一个公共结构/类,它的重载公共构造接受所需类型的参数仅包裹动态给结构/类适当的名称。
这是有道理的包裹动态总是的类/结构的私人成员,它是结构/类的唯一成员和结构的唯一成员的名字/类是“值”。
您还必须定义和实现public方法和/或操作符,如果需要,可以使用类/结构的私有动态成员的所需类型。
这也是情理之中的结构/类有特殊/独特构造接受动态作为初始化,这只是私人所谓的“价值”动态成员,但此构造的修改参数私人当然。
一旦类/结构是准备限定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"
}
}
注意的是,为了在你的代码中使用动态必须添加引用到Microsoft.CSharp
如果.NET框架的版本低于/下/较小比4.0和动态是undefi斯内德在版本,那么你将不得不使用对象,而不是和做铸造整数类型,它是麻烦,所以我建议你至少使用.NET 4.0或更高版本,如果你能这样你就可以使用动态代替对象。
我想知道为什么几个人在这里发布答案有这么多的理解概念的麻烦。在我的情况下,我想对任何整数或枚举类型执行&, - 和〜。精心设计的语言如Scala允许这样的泛型。 (即使像C++这样的蹩脚语言也允许它们) – 2013-10-19 05:52:53
另一种方法是创建一个自定义类和该类的约束,然后为每个想要支持的值类型创建隐式转换运算符。您必须在自定义约束类中实现每个&, - 和〜运算符。 – samjudson 2013-10-21 08:20:41