Я столкнулся с интересным поведением во взаимодействии между 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
, вы получите ожидаемые ошибки:
Ошибка 3 Лучший перегруженный метод, соответствующий 'ConsoleApplication2.Program .PrintCatAge(ConsoleApplication2.Program.Cat) имеет недопустимые аргументы
Ошибка 4. Аргумент 1: невозможно преобразовать из 'int?' на 'ConsoleApplication2.Program.Cat
Если вы откроете исполняемый файл с помощью ILSpy, будет сгенерирован следующий код.
int? num = null;
Program.PrintCatAge(num.HasValue ? num.GetValueOrDefault() : null);
В аналогичном эксперименте я удалил преобразование и добавил перегрузку к PrintCatAge
, которая принимает целое число (не допускающее значение NULL) в посмотрите, выполнит ли компилятор подобную операцию, но он этого не делает.
Я понимаю, что происходит, но не понимаю оправдания этому. Такое поведение для меня неожиданно и кажется странным. Мне не удалось найти какие-либо ссылки на это поведение в MSDN в документации по преобразованиям или Nullable
.
Вопрос, который я задаю, заключается в том, является ли это намеренным и есть ли объяснение, почему это происходит?