C#运算符重载使用Generic的子类

时间:2017-01-23 01:24:25

标签: c# generics operator-overloading operators

我有一个看起来像这样的结构:

public struct Vector2d<T> where T : Unit {
    public double x;
    public double y;

    ...

    public static Vector2d<Length> operator * (Vector2d<Speed> speed, Vector2d<Duration> duration) {
        return new Vector2d<Length>(speed.x * duration.x, speed.y * duration.y);
    }
}

长度,速度和持续时间类型都是Unit的子类型。 (T也继承自单位)

然而,编译器说:

  

二元运算符的一个参数必须是包含类型。

这让我很奇怪,因为提供的类型是包含类型的子类。

为什么我试图做的非法?

我知道Vector2不是Vector2的子类,但我不是试图使用泛型类型的值。运算符中使用的所有数据都是Vector2类。

2 个答案:

答案 0 :(得分:0)

根据MSDN page针对此错误:

  

二元运算符的定义指定两个参数,这些参数的类型不同于定义运算符的类或结构的类型。   在类或结构中定义运算符时,至少有一个参数必须是该类或结构的类型。

在您的情况下,您的运营商未使用Vector2d<T>类型(您使用Vector2d<Speed>Vector2d<Duration>

答案 1 :(得分:0)

运算符对声明它们的类型的实例进行操作。例如:

string one = new string(new char[] { 'o', 'n', 'e' });
string two = new string(new char[] { 't', 'w', 'o' });
if (one == two) { // do something... };

我能够使用==的原因是因为它是在String类中实现的。

您班上也有一名操作员。所以让我们使用它。但要这样做,我需要创建一个Vector2d<T>的实例,因为它是一个开放类型,我需要在实例化期间关闭它。

首先让我们这样做:

public class MyClass : Unit
{
}

现在让我们创建一个struct的实例:

var inst1 = new Vector2d<MyClass>();
var inst2 = new Vector2d<MyClass>();

这是有效的,因为MyClass正在传递T必须从Unit派生的限制。好的,我现在要使用运算符:

// Ooops MyClass is not Speed or Duration
var result = inst1 * inst2; 

这正是编译器强制执行该规则的原因,因为它希望确保操作符可以对该类型的实例进行操作。

在您的情况下,您只能为此Vector2d<T>定义运算符:

public struct Vector2d<T> where T : Unit
{
    public double x;
    public double y;

    public Vector2d(double x, double y)
    {
        this.x = x;
        this.y = y;
    }

    public static Vector2d<T> operator *(Vector2d<T> speed, Vector2d<T> duration)
    {
        return new Vector2d<T>(speed.x * duration.x, speed.y * duration.y);
    }
}

此外,您的操作员,您拥有它的方式根本不是通用的。它正在使用SpeedDurationLength,因此您正在使用这些类型。

错误二元运算符的参数之一必须是包含类型。是编译器避免让我们陷入这种麻烦的方法。我们应该感恩!