我必须定义每个运算符吗?

发布于 2024-12-27 21:35:37 字数 1685 浏览 2 评论 0原文

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

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.

因此,我实现了 IEquatableIComparable,但仍然没有启用任何运算符(甚至没有启用 ==<>= 等)。

因此,我开始提供运算符重载。

例如:

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, +, -, *, /, % , &, |, ^, <<, >>, ==, !=, <, >, <=, >=),我开始觉得一定有成为一个更好的人 方式。毕竟,该结构只包含一个字段,并且该字段是一种值类型。

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

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

Suppose I have a struct with just one field:

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);
    }
}

This works great, until I want to do stuff like this:

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

So, I implemented IEquatable<in T> and IComparable<in T>, but that still didn't enable any operators (not even ==, <, >=, etc.).

So, I started providing operator overloads.

For example:

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;
}

This worked, however, when I looked at all the operators I could conceivably overload (+, -, !, ~, ++, --, true, false, +, -, *, /, %, &, |, ^, <<, >>, ==, !=, <, >, <=, >=), I started to feel like there must be a better way. After all, the struct only contains one field, and that field is a value type.

Is there some way to enable all the operators of double in one shot? Or do I really have to type out every operator I could possibly want to support by hand?

(Even if I had two or three fields, I'd still like to be able to add the operators in one batch...)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一江春梦 2025-01-03 21:35:37

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

根据记录,如果您确实只需要一个字段,并且它只是一个双精度值,那么首先不要使用结构体,除非您需要重载运算符来执行默认情况下执行的其他操作 -  这是一个明显的过度设计案例!

The point of overloading operators is to define how to add to manipulate objects of a custom type using those operators, so if your second field was a string array, how would you expect the ++ operator to be implemented automatically? There is no sensible answer, especially since we don't know the context of the object or it's usage, so the answer is yes, you do have to overload the operators yourself.

For the record, if you really do only need one field, and it's just a double, then don't use a struct in the first place unless you need to overload the operators to perform some other action than they do by default — it's a clear case of over-engineering!

绅刃 2025-01-03 21:35:37

是的,您必须定义要使用的每个运算符。编译器无法知道您希望每个运算符做什么,除了彼此相反的运算符(甚至这些运算符也不一定很明显;如果您想模仿标准 SQL null 行为,其中两个 ==!= 与 null 相比会返回 false?)。

Yes, you must define every operator that you want to use. The compiler has no way of knowing what you want each operator to do, aside from the operators that are negatives of each other (and even those may not necessarily be obvious; what if you wanted to mimic standard SQL null behavior where both == and != would return false when compared to null?).

扛刀软妹 2025-01-03 21:35:37

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

我不确定 C# 中注释的限制是什么,但也许可以创建一个注释来实现这一点(对于返回 bool 的运算符),但除非您非常打算使用它,否则我怀疑它是否值得你的时间。

话虽如此,如果您有一个对象在构造函数中只接受一个参数,并且该参数是该方法的返回值,那么也应该可以做到这一点。

当然,要做到这些都需要一些相当极端的阶级修补,我真的无法提供建议......

For most cases I agree with LaceySnr: it doesn't really work for any operators that return your new object (e.g. +, * ect.). For the comparators it could work (as in there could be an annotation that says "use this method's return value to stand in for for this object when used in all comparator operations"), but I don't know of anything like that.

I'm not sure what the limitations of annotations are in C#, but it may be possible to create one that does that (for the operators that return bool), but unless you were planning on using it very much I doubt it will be worth your time.

Having said this, if you were to have an object which took exactly one argument into the constructor, and that argument was the return value of the method, it should be possible to do it for that as well.

Of course to do any of this will require some pretty extreme class-tinkering, which I'm not really in a situation to give advice on...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文