题
谁能告诉我如果有一种方法有仿制药的限制一般类型参数 T
只有:
Int16
Int32
Int64
UInt16
UInt32
UInt64
我知道的 where
关键字,但不能找到一个接口 只 这些类型
是这样的:
static bool IntegerFunction<T>(T value) where T : INumeric
解决方案
C#不支持这一点。Hejlsberg有所描述的原因不执行的要素 在采访布鲁爱可尔:
它不清楚的是,所增加的复杂性是值得的产量小,你得到的。如果你想要的东西做的是不是直接支持在约束的体系,你可以做到这一工厂的模式。你可以有一个
Matrix<T>
, 例如,在这Matrix
你会喜欢的定义一点的产品的方法。那当然那意味着你最终需要了解如何乘两个T
s,但你不能说,作为约束,至少不是如果T
是int
,double
, 或float
.但你能做什么是有你Matrix
作为一个参数的一个Calculator<T>
, ,并在Calculator<T>
, 有一个方法被称为multiply
.你去实施,并传递给Matrix
.
然而,这导致相当令人费解的代码,其中的用户提供他们自己 Calculator<T>
执行,对每一个 T
他们想要使用。只要它不具有可扩展性,即如果你只是想支持一个固定数量的类型,例如 int
和 double
, 你可以得到一个相对较简单的界面:
var mat = new Matrix<int>(w, h);
然而,只要你想让用户能够提供自己的定义类型,你需要打开这个执行情况,以便用户能够提供自己的 Calculator
实例。例如,要实例化的矩阵,使用十进制定浮点实施, DFP
, 你必须写这些代码:
var mat = new Matrix<DFP>(DfpCalculator.Instance, w, h);
...和实现所有的成员 DfpCalculator : ICalculator<DFP>
.
一种选择,不幸的是,股份相同的限制,是以工作与政策课程, 作为讨论的谢尔盖Shandar的答案.
其他提示
考虑到普及,这个问题和感兴趣的背后,这一功能我惊讶地看到,没有回答涉及T4。
在这样的代码,我会证明一个非常简单的例子可以如何使用功能强大的模板发动机来做什么的编译器几乎不的幕后有仿制药。
而不是通过篮球和牺牲的编写时肯定你可以简单地产生功能你想要的每一个你喜欢的类型和使用,因此(在编制时间!).
为了做到这一点:
- 创建一个新的 文本的模板 文件称为 GenericNumberMethodTemplate.tt.
- 删除自动产生的代码(你会保持它的大部分,但是一些不需要的)。
- 添加以下一段:
<#@ 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();
}
}
}
我会得到今后的一句话:不,这不是违反了干原则。干原则是否有防止人们重复代码在多个地方,这将会导致应用程序变得难以维持。
这不是在所有情况:如果你想改变那么你可以改变的模板(一种单一来源对所有生!) 它的完成。
为了使用自己的定义定义,增添一个名字空间的宣言》(确定它是同一个作为一个在那里你定义自己的执行)到你产生的代码和标志的类 partial
.之后,添加这些行为模板的文件,所以它将被包括在最终汇编:
<#@ import namespace="TheNameSpaceYouWillUse" #>
<#@ assembly name="$(TargetPath)" #>
让我们实话实说:这是很酷。
免责声明:这个样品已经被严重影响 元编程。净由凯文*哈扎德和贾森*博克曼宁的出版物.
有没有约束这一点。这是一个真正的问题对任何人想要使用仿制药对数字计算。
我会去进一步说,我们需要
static bool GenericFunction<T>(T value)
where T : operators( +, -, /, * )
甚至
static bool GenericFunction<T>(T value)
where T : Add, Subtract
遗憾的是你只有接口基类和关键词 struct
(必须是值型), class
(必须参照类型)和 new()
(必须有default constructor)
你能包裹数量在别的东西(类似于 INullable<T>
)像 在这里上演示.
你可以申请限制在运行时(通过反映的营运者或检查类型),但不丧失其优点是具有一般放在第一位。
解决方法使用政策:
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框架 提供汇编的版本。净4.0.该文件lib/NETFramework4.0/CityLizard.Policy.dll.
它也可以在Nuget: https://www.nuget.org/packages/CityLizard/.看看 CityLizard.政策。我 结构。
这个问题的一个常见问题之一,因此我要发布这一作wiki(因为我已经发布类似之前,但这是一个旧的一个);无论如何...
什么样的版本。净你用?如果您使用。净3.5,然后我有一个 通用经营执行情况 在 MiscUtil (免费等)。
这方法一样 T Add<T>(T x, T y)
, 和其他的变种,用于算术上的不同类型(喜欢 DateTime + TimeSpan
).
此外,这适用于所有内置,提升和定制的运营商,并缓存的代表性。
一些额外背景上为什么这是件棘手的是 在这里,.
你也可能想知道 dynamic
(4.0)进行排序的解决这个问题,间接地太-即
dynamic x = ..., y = ...
dynamic result = x + y; // does what you expect
不幸的是你是唯一能够指定的结构在其条款中的这个实例。它看起来很奇怪你不能指定Int16,Int32,等等。具体地说但我确定存在的一些深层次的执行理潜在的决定不允许值类型,在其中的条款。
我想唯一的解决办法是做一个运行时检查其不幸的是防止问题正在汇编的时间。那会去的东西,如:-
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...
}
这是一点点丑,我知道,但是至少提供了所需要的约束。
我也看到可能的绩效的影响,为此实施,也许有一个更快捷的方式。
可能接近你可以做的是
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>
为什么这么具体的,为什么不只是过载于各个类型,该名单是如此之短,可能会有较少的内存占用。
有没有办法来限制模板类型,但可以界定不同行动基础上的类型。作为一部分的一个通用的数字包,我需要一个通用类添加两个价值观。
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进行评估,在编制时间,所以如果发言将通过编译器。编译器也去除虚假的转换。这样事情会解决在编译器
internal static int Sum(int first, int second)
{
return first + second;
}
我创建了一个小小的图书馆的功能来解决这些问题:
代替:
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
我想知道同样如samjudson,为什么只有以整数?如果是这种情况下,你可能希望创建一个助手一类或类似的东西,保持所有的类型你想要的。
如果你想要的都是整体、不使用通用的,这不是一般;或者更好的是,拒绝任何其他类型的检查类型。
什么是点锻炼吗?
正如人们指出已经,你可以有一个非通用功能把最大的项目,并编译器将会自动转换较小的int你。
static bool IntegerFunction(Int64 value) { }
如果你的功能性能至关重要的路径(非常不可能的,海事组织),可以提供重载于需要的所有功能。
static bool IntegerFunction(Int64 value) { }
...
static bool IntegerFunction(Int16 value) { }
我会用一个通用的一个,你可以处理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
都
- 性能。所有价值类,获得装箱。
- 运行时的错误。你"打败"编译器,但损失类型的安全。如果通用类型没有操作者的定义,一个例外将被抛在执行过程中。
没有"良好的"解决方案。但是你可以缩小型的论点明显排除了许多missfits你hypotetical'INumeric'约束作为Haacked有上所示。
静态bool IntegerFunction<T>(T值)在T:类,IFormattable,请参型<T>果需要修改<T>、结构 {...
。净额数字的基本类型不分享任何共同的接口将允许它们被用于计算。这将有可能界定自己的接口(如 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()
法)。这种方法就失去了优势相关的编写时间类型检查,但仍将管理,以避免拳击行动和每种类型的就只有被"检查"一次。在此之后,运作相关的类型将取代与一代表派遣。
如果您使用。净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.
}
当然,这一解决方案的工作在运行时间仅但从来没有在编制时间。
如果你想要一个解决方案,总是在编制时间,从来没有在运行时间,然后你将来包裹 动态 与公共struct/类,其超载 公共 造接受参数的所需类型和给予的结构/流的适当名称。
这是有道理的,该包裹 动态 总是 私 成员的舱位/结构,它是仅有的成员结构/类和名称的唯一的成员结构/类是"价值"。
你也会需要定义和执行 公共 方法和/或经营者的工作,与需要类型的私人动态部件的类/struct如果有必要的。
它还有意义的结构/类 特殊/独特 构造接受 动态 作为论点,即初始化这只是私人动成员称为"价值"但是 修改 这个构造是 私 当然。
一旦类/struct准备好界定参数的种类型的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。C#
如果该版本的.净框架低、欠低于4.0 动态 是不确定的在版本,然后你会有用 对象 而不是和做铸到整数类型,这是麻烦,所以我建议你使用最少。净4.0或更新的,如果你可以你可以用 动态 而不是的 对象.
如果你想要的是使用 一个数字型, 你可以考虑建立类似的东西别在C++ using
.
因此,而不是具有非常一般
T ComputeSomething<T>(T value1, T value2) where T : INumeric { ... }
你可以
using MyNumType = System.Double;
T ComputeSomething<MyNumType>(MyNumType value1, MyNumType value2) { ... }
这能让你轻松去 double
要 int
或其他人如果需要的话,但你不能使用 ComputeSomething
与 double
和 int
在同一程序。
但是,为什么不替换所有的 double
要 int
然后呢?因为你的方法可能想要使用 double
是否输入 double
或 int
.别让你知道到底哪个变量使用的 动态 类型。
我有一个类似的情况下,我需要处理的数值类型和串;似乎有点奇怪的混但那里你去。
再次,许多人我看着限制,并提出了一堆的接口,它必须支持。然而,一)它不是100%的水和b),任何人寻找新的,在这个长长的清单的约束,将立即非常困惑。
因此,我的办法就是把我所有的逻辑成一个通用的方法没有限制,但要使该一般方法私人的。然后我暴露了它与公共方法,一种明确处理的类型,我想到处理到我的心灵,代码是干净的和明确的,例如
public static string DoSomething(this int input, ...) => DoSomethingHelper(input, ...);
public static string DoSomething(this decimal input, ...) => DoSomethingHelper(input, ...);
public static string DoSomething(this double input, ...) => DoSomethingHelper(input, ...);
public static string DoSomething(this string input, ...) => DoSomethingHelper(input, ...);
private static string DoSomethingHelper<T>(this T input, ....)
{
// complex logic
}
没有一个单一的接口或基类,他们所有继承(这是不是也继承了其他类别)这样简单的回答是没有。
我不知道为什么这个问题。什么是你想要做你的内IntegerFunction类只能做到整数?
我想你是误会仿制药。如果操作你都在试图执行的是仅有益于具体数据类型,那么你不做一些"普通".
此外,由于你只是想让的功能的工作int数据类型,那么你不应该需要一个单独的功能对每个特定大小。只是一个参数在最大的特定类型将使程序自动向上转换较小的数据类型。(即通过Int16将自动转换到Int64打电话时).
如果执行不同的操作基础上的实际尺寸int正在通过进入功能,那么我会认为你应该认真重新考虑,甚至试图做的你在做什么。如果你必须傻瓜的语言,则应认为更多一点关于你设法完成,而不是如何做你想做的。
失败的一切类型的参数的对象可以使用,然后你会检查的类型参数,并采取适当的行动,或扔一个例外。