我是否必须定义每个运营商?

时间:2012-01-19 03:28:31

标签: c# .net struct operators operator-overloading

假设我的结构只有一个字段:

public struct Angle
{
    public static readonly double RadiansPerDegree = Math.PI / 180;

    private readonly double _degrees;

    public Angle(double degrees)
    {
        _degrees = degrees;
    }

    public double Degrees
    {
        get { return _degrees; }
    }

    public double Radians
    {
        get { return _degrees * RadiansPerDegree; }
    }

    public static Angle FromDegrees(double value)
    {
        return new Angle(value);
    }

    public static Angle FromRadians(double value)
    {
        return new Angle(value / RadiansPerDegree);
    }
}

这很有效,直到我想做这样的事情:

var alpha = Angle.FromDegrees(90);
var beta = Angle.FromDegrees(100);
var inequality = alpha > beta;
var sum = alpha + beta;
var negation = -alpha;
//etc.

所以,我实施了IEquatable<in T>IComparable<in T>,但仍未启用任何运营商(甚至不==<>=等)。

所以,我开始提供运算符重载。

例如:

public static Angle operator +(Angle a, Angle b)
{
    return new Angle(a._degrees + b._degrees);
}

public static Angle operator -(Angle a)
{
    return new Angle(-a._degrees);
}

public static bool operator >(Angle a, Angle b)
{
    return a._degrees > b._degrees;
}

然而,当我查看所有我可以想象的重载(+, -, !, ~, ++, --, true, false, +, -, *, /, %, &, |, ^, <<, >>, ==, !=, <, >, <=, >=)的操作符时,这很有用,我开始觉得必须有更好的方法。毕竟,struct只包含一个字段,该字段是值类型。

有没有办法一次性启用double的所有操作符?或者我真的必须输入我可能想要手工支持的每个操作员吗?

(即使我有两个或三个字段,我仍然希望能够在一个批次中添加运算符...)

3 个答案:

答案 0 :(得分:12)

重载运算符的重点是定义如何使用这些运算符来添加操作自定义类型的对象,因此如果第二个字段是字符串数组,那么您希望如何自动实现++运算符?没有合理的答案,特别是因为我们不知道对象的上下文或它的用法,所以答案是是的,你必须自己重载操作符

对于记录,如果你真的只需要一个字段,并且它只是一个double,那么首先不要使用结构,除非你需要重载运算符来执行一些其他操作,而不是默认情况下执行 - 这是一个过度工程的明显案例!

答案 1 :(得分:0)

是的,您必须定义要使用的每个运算符。除了彼此否定的运算符之外,编译器无法知道你希望每个运算符做什么(甚至那些可能不一定是显而易见的;如果你想模仿标准的SQL null行为,那么{{1与null相比,{}和==会返回!=

答案 2 :(得分:0)

对于大多数情况,我同意LaceySnr:它并不适用于任何返回新对象的运算符(例如+,*等)。对于比较器,它可以工作(因为可能有一个注释说“在所有比较器操作中使用时,使用此方法的返回值代表该对象”),但我不知道类似的事情。 / p>

我不确定注释在C#中的局限性,但是有可能创建一个这样做(对于返回bool的运算符),但除非你计划使用它非常多我怀疑它值得你花时间。

说完这个,如果你有一个对象只有一个参数进入构造函数,并且该参数是方法的返回值,那么也应该可以为它做这个。

当然要做任何这些都需要一些非常极端的修补,我真的不是在提供建议......