,这是什么可空的理由 与隐式转换经营行为(What is the justification

2019-07-29 00:40发布

我遇到之间的相互作用一些有趣的行为Nullable和隐式转换。 我发现,对于从一个值的参考类型的提供的隐式转换键入它允许Nullable类型将被传递到需要引用类型时,我期望代替一个编译错误的功能。 下面的代码说明了这一点:

static void Main(string[] args)
{
    PrintCatAge(new Cat(13));
    PrintCatAge(12);
    int? cat = null;
    PrintCatAge(cat);
}

private static void PrintCatAge(Cat cat)
{
    if (cat == null)
        System.Console.WriteLine("What cat?");
    else
        System.Console.WriteLine("The cat's age is {0} years", cat.Age);
}

class Cat
{
    public int Age { get; set; }
    public Cat(int age)
    {
        Age = age;
    }

    public static implicit operator Cat(int i)
    {
        System.Console.WriteLine("Implicit conversion from " + i);
        return new Cat(i);
    }
}

输出:

The cat's age is 13 years
Implicit conversion from 12
The cat's age is 12 years
What cat?

如果转换代码从删除Cat ,那么你获得预期的错误:

Error 3 The best overloaded method match for 'ConsoleApplication2.Program.PrintCatAge(ConsoleApplication2.Program.Cat)' has some invalid arguments

Error 4 Argument 1: cannot convert from 'int?' to 'ConsoleApplication2.Program.Cat

如果你打开可执行文件ILSpy生成的代码如下:

int? num = null;
Program.PrintCatAge(num.HasValue ? num.GetValueOrDefault() : null);

在类似的实验予除去转换和加入的过载到PrintCatAge接受一个int(不可为空),看看是否编译器将执行类似的操作,但是它没有。

我明白发生了什么,但我不明白它的理由。 此行为是意外,我和似乎很奇怪。 我没有任何成功找到文档中的转换或MSDN上这种行为的任何引用Nullable<T>

这个问题我带来然后,这是故意的,有没有为什么会这样一个解释吗?

Answer 1:

我刚才说,(1)这是一个编译器错误和(2)它是一个新的。 第一个说法是准确的; 第二次是我感到困惑,我急忙去上车时间。 (我在想的是,错误是新的我是一个更复杂的bug,涉及解禁的转换和提升增量的运营商。)

这是长期的一个已知的编译器错误。 乔恩斯基特首先,它带给我的注意,前一段时间,我相信有地方关于它的StackOverflow问题; 我不记得在那里随便。 也许乔恩做。

因此,错误。 让我们定义一个“取消”操作。 如果操作者从非空值类型S转换到非空值类型T,然后还有一个“取消”操作符,选自S转换? 以T 2使得空S' 转换为空T' 和一个非空S' 转换到T? 通过展开S' 到S,转换s到T,和包裹吨至T?

说明书中指出,(1)的唯一的情况,其中有一个提升运算符是当S和T均为非空值类型,和(2)的提升和非提升转换运算符被认为是否他们是用于转换应用于候选,并且如果这两个应用,则适用转换,提升或未提升的源和目标类型,被用来确定最佳的光源类型,最佳目标类型,最终,所有适用的转化的最佳转化率。

不幸的是,实施彻底违反了所有这些规则,在这我们不能改变在不破坏现有的许多程序的方式这样做。

首先,我们对违反运营商解禁的存在规则。 甲提升运算符由实现视为存在如果S和T均为非空值类型,或者如果S是一个非空值类型和T是其中虚假可分配任何类型的:引用类型,可为空值型,或指针类型。 在所有这些情况下,我们产生一个提升运算符。

你的具体情况,我们上调可空说我们通过检查空转换可空类型的引用类型猫。 如果源不是null,则我们通常转换; 如果是这样,那么我们生产的空目录。

其次,我们彻底违反有关如何确定最佳的源和目标类型适用的候选人时,这些候选人之一是提升运算规则,我们也违反了有关确定这是最好的操作规则。

总之,这是一个很大的混乱,无法固定而不会破坏真正的客户,所以我们可能会供奉在罗斯林的行为。 我会考虑在某一时刻记录在我的博客编译器的具体行为,但在等待的那一天,如果我是你,我不会认为我的呼吸。

当然还有很多道歉的错误。



文章来源: What is the justification for this Nullable behavior with implicit conversion operators