隐式转换如何与运算符重载一起使用?

How do implicit conversions work with operator overloading?

比如说,如果我出于某种原因在浮点类型周围创建一个薄包装器,就像这样:

public class WrappedFloat
{

    private float value;

    public WrappedFloat(float value)
    {
        this.value = value;
    }

    public static implicit operator float(WrappedFloat wrapped)
    {
        return wrapped.value;
    }

    public static implicit operator WrappedFloat(float value)
    {
        return new WrappedFloat(value);
    }

}

此代码显然完全有效:

new WrappedFloat(4.0F) + new WrappedFloat(3.0F)

因为 WrappedFloat 没有定义任何算术运算符,所以一定有一些关于它到 float 的隐式转换允许这样做。但是运算符重载只是方法的语法糖,对吧?这不像我可以在 WrappedFloat 上调用方法(即 CompareTo)只是因为 float 有它们。那么这里的运算符有什么特别之处呢?允许这样做的规则是什么?

就本次讨论而言,运算符就像静态方法一样。想象一下,每个运算符重载都有一个实际的静态方法:

public static int Plus(int a, int b) { return a + b; }
public static float Plus(float a, float b) { return a + b; }
public static long Plus(long a, long b) { return a + b; }
public static string Plus(string a, string b) { return a + b; }
public static double Plus(double a, double b) { return a + b; }
//...

现在假设您有:

Plus(new WrappedFloat(4.0F), new WrappedFloat(3.0F));

您希望这里发生什么?重载解析会 运行,它会发现有一个重载,其两个参数都有一个隐式转换,并且该重载(接受 float 值)成为唯一的最佳匹配。

运算符也会发生完全相同的事情。它将所有重载放在一起,查看哪些重载具有可以隐式转换为所提供参数的参数列表,如果有多个重载,则从中选择最佳匹配。

But operator overloading is just syntactic sugar for methods, right?

它不是"methods"的语法糖,它是一种以特定方式实现的方法的语法糖。使用 . 语法对对象的典型方法调用在这里不适用。 MS 选择了一种方便程序员的设计。当我打电话时

wrappedFloat.Method()

我不希望它在 wrappedFloat 上寻找所有可能性,但是当我这样做时

wrappedFloat1 + wrappedFloat2

我希望如此。我在这里同意 MS。这里的一个区别是,第一种情况是对实例的调用,第二种是静态方法调用,其中形式参数作为参数传递。