在通用c#结构中使用运算符

在通用c#结构中使用运算符,c#,generics,C#,Generics,我正在写一个通用的C#struct。我有以下资料: struct GenericPoint<T> where T : IComparable, IFormattable, IConvertible, IComparable<T>, IEquatable<T> { T x; T y; GenericPoint(T x, T y) { this.x = x; this.y = y; } static GenericPoint

我正在写一个通用的C#struct。我有以下资料:

struct GenericPoint<T> where T : IComparable, IFormattable, IConvertible, IComparable<T>, IEquatable<T> {
  T x;
  T y;

  GenericPoint(T x, T y) {
    this.x = x;
    this.y = y;
  }

  static GenericPoint<T> operator +(GenericPoint<T> p1, GenericPoint<T> p2) {
    GenericPoint<T> r;
    r.x = (dynamic) p1.x + p2.x;
    r.y = (dynamic) p1.y + p2.y;
    return r;
  }
struct generic点,其中T:i可比较、i可附加、i可转换、i可比较、i可计算{
tx;
T y;
一般点(T x,T y){
这个.x=x;
这个。y=y;
}
静态GenericPoint运算符+(GenericPoint p1,GenericPoint p2){
一般点r;
r、 x=(动态)p1.x+p2.x;
r、 y=(动态)p1.y+p2.y;
返回r;
}

这会起作用,但有更好的方法吗?我的意图是T将是一种了解“+”运算符的类型。我很高兴在编译时做出承诺。但这是可能的吗?

不幸的是,C#泛型无法做到这一点

这就是为什么,例如,
.NET
框架提供了,
矩形
矩形
,其中这些结构的定义基本上是彼此重复的,
int
浮点
,而不是想要的“通用”类型


但是,如果你真的想这么做

  • 创建一个
    IMath
    界面。(如果你喜欢冒险,甚至可以创建
    IField
    。请参见此处:)

  • 在“程序初始化”期间为您想要支持的每种类型设置
    GenericPoint.TMath
    GenericPoint.TMath
    ,等等。如果您无意中尝试将
    GenericPoint
    类与未指定
    IMath
    的某个类型一起使用,则在使用op时只会得到
    NullReferenceException
    埃拉托斯


  • 不幸的是,C#泛型无法做到这一点

    这就是为什么,例如,
    .NET
    框架提供了,
    矩形
    矩形
    ,其中这些结构的定义基本上是彼此重复的,
    int
    浮点
    ,而不是想要的“通用”类型


    但是,如果你真的想这么做

  • 创建一个
    IMath
    界面。(如果你喜欢冒险,甚至可以创建
    IField
    。请参见此处:)

  • 在“程序初始化”期间为您想要支持的每种类型设置
    GenericPoint.TMath
    GenericPoint.TMath
    ,等等。如果您无意中尝试将
    GenericPoint
    类与未指定
    IMath
    的某个类型一起使用,则在使用op时只会得到
    NullReferenceException
    埃拉托斯


  • 你想做的事你做不到(我希望能够做到)。问题是在C#接口中不允许运算符重载。因此,尽管你可以约束()你的泛型变量('t')如果将其约束到接口,它将不知道您有一个“+”运算符。您可以使用重载的适当运算符定义基类,但必须将“t”约束为基于该类(因此不能使用任何值类型,如int、double等),或不基于用作约束的对象的对象。您的动态解决方案实际上相当不错,最大的问题当然是您短路了任何编译时警告,因此,如果您使用的类不支持“+”,则在运行时失败之前,您不会知道它。

    您想做什么,您不能(我希望能够做到)。问题是,在C#interface中不允许运算符重载。因此,虽然您可以()约束泛型变量('t'),但如果将其约束到接口,它将不知道您有一个“+”运算符。您可以定义一个重载了相应运算符的基类,但必须约束“t”以该类为基础(因此不能使用int、double等任何值类型),或不基于用作约束的对象的对象。您的动态解决方案实际上相当不错,最大的问题当然是您短路了任何编译时警告,因此如果您使用不支持“+”的类,则在运行时失败之前您不会知道它。

    有一种稍微简单的方法。使用Linq.Expressions是可行的假设您愿意在运行时接受错误(如果类型不支持该操作),则可以创建将以通用方式执行所需数学操作的委托。 这实际上更容易的唯一原因是已经完成了,请参见:

    使用Operator.cs中定义的静态运算符类,可以将动态强制转换替换为:

    r.x = (dynamic) p1.x + p2.x;
    r.y = (dynamic) p1.y + p2.y;
    
    变成:

    r.x = Operator<T>.Add(p1.x, p2.x);
    r.y = Operator<T>.Add(p1.y, p2.y);
    
    r.x=Operator.Add(p1.x,p2.x);
    r、 y=运算符.Add(p1.y,p2.y);
    
    有一种稍微简单一点的方法。使用Linq.Expressions可以创建以通用方式执行所需数学操作的委托,前提是如果类型不支持该操作,您愿意在运行时接受错误。 这实际上更容易的唯一原因是已经完成了,请参见:

    使用Operator.cs中定义的静态运算符类,可以将动态强制转换替换为:

    r.x = (dynamic) p1.x + p2.x;
    r.y = (dynamic) p1.y + p2.y;
    
    变成:

    r.x = Operator<T>.Add(p1.x, p2.x);
    r.y = Operator<T>.Add(p1.y, p2.y);
    
    r.x=Operator.Add(p1.x,p2.x);
    r、 y=运算符.Add(p1.y,p2.y);
    
    C泛型不是C++模板。谢谢;固定了POST。操作员的实现不是必须公开的吗?C泛型不是C++模板。谢谢;固定了帖子。难道操作符的实现不是必须公开的吗?