Tri*_*nko 30 c# generics math operator-overloading primitive-types
给出类似的泛型类定义
public class ConstrainedNumber<T> :
IEquatable<ConstrainedNumber<T>>,
IEquatable<T>,
IComparable<ConstrainedNumber<T>>,
IComparable<T>,
IComparable where T:struct, IComparable, IComparable<T>, IEquatable<T>
Run Code Online (Sandbox Code Playgroud)
如何为它定义算术运算符?
以下内容无法编译,因为'+'运算符不能应用于类型'T'和'T':
public static T operator +( ConstrainedNumber<T> x, ConstrainedNumber<T> y)
{
return x._value + y._value;
}
Run Code Online (Sandbox Code Playgroud)
正如您所见,泛型类型'T'受'where'关键字约束,但我需要对具有算术运算符的数字类型(IArithmetic?)进行约束.
'T'将是一个原始数字类型,如int,float等.这些类型是否存在'where'约束?
And*_*are 15
遗憾的是,没有办法将泛型参数约束为整数类型(编辑:我猜"算术类型"可能是一个更好的词,因为这不仅仅与整数有关).
能够做这样的事情会很高兴:
where T : integral // or "arithmetical" depending on how pedantic you are
Run Code Online (Sandbox Code Playgroud)
要么
where T : IArithmetic
Run Code Online (Sandbox Code Playgroud)
我建议您通过我们自己的Marc Gravell和Jon Skeet 阅读Generic Operators.它解释了为什么这是一个如此困难的问题,以及可以采取哪些措施来解决它.
.NET 2.0在.NET世界中引入了泛型,为现有问题的许多优雅解决方案打开了大门.通用约束可用于将类型参数限制为已知接口等,以确保对功能的访问 - 或者对于简单的相等/不等式测试,Comparer.Default和EqualityComparer.Default单例分别实现IComparer和IEqualityComparer(允许我们对元素进行排序)例如,无需了解有关"T"的任何信息.
尽管如此,在运营商方面仍存在很大差距.因为运算符被声明为静态方法,所以没有所有数值类型实现的IMath或类似的等效接口; 事实上,运营商的灵活性会使这项工作变得非常困难.更糟糕的是:原始类型的许多运算符甚至不作为运算符存在; 相反,有直接的IL方法.[强调我的]为了使情况更加复杂,Nullable <>要求"提升运算符"的概念,其中内部"T"描述适用于可空类型的运算符 - 但这是作为语言特征实现的,并且是不是由运行时提供的(使反射更有趣).
Dan*_*fer 15
我认为你能做的最好的事情是IConvertible
用作约束并做类似的事情:
public static operator T +(T x, T y)
where T: IConvertible
{
var type = typeof(T);
if (type == typeof(String) ||
type == typeof(DateTime)) throw new ArgumentException(String.Format("The type {0} is not supported", type.FullName), "T");
try { return (T)(Object)(x.ToDouble(NumberFormatInfo.CurrentInfo) + y.ToDouble(NumberFormatInfo.CurrentInfo)); }
catch(Exception ex) { throw new ApplicationException("The operation failed.", ex); }
}
Run Code Online (Sandbox Code Playgroud)
这不会阻止某人传递String或DateTime,所以你可能想要做一些手动检查 - 但IConvertible应该让你足够接近,并允许你进行操作.
Ric*_*dOD 12
在C#4.0中,您可以使用动态来绕过此限制.我查看了你的代码,并设法生成了一个工作(虽然削减)版本:
public class ConstrainedNumber<T> where T : struct, IComparable, IComparable<T>, IEquatable<T>
{
private T _value;
public ConstrainedNumber(T value)
{
_value = value;
}
public static T operator +(ConstrainedNumber<T> x, ConstrainedNumber<T> y)
{
return (dynamic)x._value + y._value;
}
}
Run Code Online (Sandbox Code Playgroud)
还有一个小测试程序:
class Program
{
static void Main(string[] args)
{
ConstrainedNumber<int> one = new ConstrainedNumber<int>(10);
ConstrainedNumber<int> two = new ConstrainedNumber<int>(5);
var three = one + two;
Debug.Assert(three == 15);
Console.ReadLine();
}
}
Run Code Online (Sandbox Code Playgroud)
请享用!
C# 11 / .NET 7 给了我们这个:
public class ConstrainedNumber<T> where T : INumber<T>
{
T _value;
public static T operator +(ConstrainedNumber<T> x, ConstrainedNumber<T> y)
{
return x._value + y._value;
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
24671 次 |
最近记录: |