当前位置:  开发笔记 > 编程语言 > 正文

为什么C#编译器不调用隐式转换运算符?

如何解决《为什么C#编译器不调用隐式转换运算符?》经验,为你挑选了2个好方法。

假设我们有以下类型:

struct MyNullable where T : struct
{
    T Value;

    public bool HasValue;

    public MyNullable(T value)
    {
        this.Value = value;
        this.HasValue = true;
    }

    public static implicit operator T(MyNullable value)
    {
        return value.HasValue ? value.Value : default(T);
    }
}

并尝试编译以下代码片段:

MyNullable i1 = new MyNullable(1);
MyNullable i2 = new MyNullable(2);

int i = i1 + i2;

剪切得很好,没有错误.i1和i2转换为整数和加法评估.

但如果我们有以下类型:

struct Money
{
    double Amount;
    CurrencyCodes Currency; /*enum CurrencyCode { ... } */

    public Money(double amount, CurrencyCodes currency)
    {
        Amount = amount;
        Currency = currency;
    }

    public static Money operator + (Money x, Money y)
    {
        if (x.Currency != y.Currency)
            // Suppose we implemented method ConvertTo
            y = y.ConvertTo(x.Currency); 

        return new Money(x.Amount + y.Amount, x.Currency);
    }
}

尝试编译另一个代码段:

MyNullable m1 = 
   new MyNullable(new Money(10, CurrenciesCode.USD));
MyNullable m2 = 
   new MyNullable(new Money(20, CurrenciesCode.USD));

Money m3 = m1 + m2;

现在问题是,为什么编译器生成" 错误CS0019:运算符'+'不能应用于'MyNullable '和'MyNullable '类型的操作数 "?



1> Marc Gravell..:

这是一个有趣的问题...... Decimal例如,它可以使用,但不是TimeSpan,它们都是正确的.NET类型(不像float是原始的类型)并且都有+运算符.好奇!

当然,你可以扭动手臂:

Money m3 = (Money)m1 + (Money)m2;

它你只是Nullable免费使用它,当然 - 加上你得到编译器+运行时(拳击)支持.有没有理由不在Nullable这里使用?

我会看看规格; 在此期间,您可能会考虑将运营商推广到MyNullable; 通常Nullable,C#编译器为类型支持的操作符提供"提升"操作符,但你不能自己做.您可以做的最好的是提供所有明显的,并希望类型支持它;-p要访问具有泛型的运算符,请参阅此处,可在此处免费下载.

请注意,您可能希望应用适当的"提升"检查 - 即

x + y => (x.HasValue && y.HasValue)
          ? new MyNullable(x.Value + y.Value)
          : new MyNullable();

更新

不同的处理看起来与14.7.4(ECMA 334 v4)"加法运算符"有关,其中它是为包括十进制在内的一系列类型预先定义的(因此这对我来说是一次糟糕的测试),因为14.2.4(相同)"二元运算符重载分辨率",预定义运算符确实得到特别提及.不过,我并没有声称完全理解它.



2> Jon Skeet..:

Marc在右边 - 它是C#3.0规范中的第7.2.4节 - 二进制运算符重载决议.

基本上步骤是:

我们需要解决"X + Y"的实现,其中X和Y都是MyNullable.

查看7.2.5节(候选用户定义的运算符),我们最终得到一个空集,因为MyNullable不会重载+.

回到7.2.4,候选运算符集是+的内置二元运算符集,即int + int,十进制+十进制等.

然后应用7.4.3中的过载分辨率规则.当我们这样做MyNullable + MyNullable是因为每个参数的隐式转换int- 但是当我们这样做时MyNullable + MyNullable不起作用,因为Money + Money它不在候选运算符集中.

推荐阅读
周扒pi
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有