Я обнаружил некоторое интересное поведение во взаимодействии между 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 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 age is 13 years
Implicit conversion from 12
The cat 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 (не может быть nullable), чтобы увидеть, выполнит ли компилятор аналогичную операцию, но это не так.
Я понимаю, что происходит, но я не понимаю его оправдания. Такое поведение неожиданно для меня и кажется странным. Мне не удалось найти какую-либо ссылку на это поведение в MSDN в документации для конверсий или Nullable<T>
.
Затем я задаю вопрос: является ли это преднамеренным и есть ли объяснение, почему это происходит?