Согласно спецификации C#, Интерполированные строки , существует неявное преобразование из интерполированной строки в FormattableString
:
interpolated_string_expression - это классифицируется как стоимость. Если он немедленно преобразуется в System.IFormattable
или System.FormattableString
с неявным преобразованием интерполированной строки ( Неявное интерполированное преобразование строки ), интерполированное строковое выражение имеет этот тип. В противном случае он имеет тип string
.
. В предоставленном коде также выполняется преобразование string
в StringIfNotFormattableStringAdapter
.
Вызов метода
Log($"Hello");
можно разрешить для обоих методов Log
, поскольку интерполированное строковое выражение $"Hello"
может быть:
- неявно преобразовано в
FormattableString
как интерполированная строка; - неявно преобразовано на
StringIfNotFormattableStringAdapter
как string
.
Здесь возникает неоднозначность для компилятора, и для ее устранения необходимы дополнительные правила. Для устранения неоднозначности компилятор использует правила, описанные в C# Спецификация, Лучшая цель конверсии (go в нижней части страницы 164) . Правила гласят:
Учитывая два различных типа T1
и T2
, T1
является лучшей целью преобразования, чем T2
, если неявное преобразование из T2
в T1
существует, и по крайней мере одно из следующих условий:
В приведенном коде FormattableString
лучше преобразование, чем StringIfNotFormattableStringAdapter
, потому что
- нет неявного преобразование из
StringIfNotFormattableStringAdapter
в FormattableString
и
- существует неявное преобразование из
FormattableString
в StringIfNotFormattableStringAdapter
.
Поэтому компилятор предпочитает преобразовывать интерполированную строку $"Hello"
в FormattableString
, а затем вызывает метод Log(FormattableString)
.
Почему удаление
implicit operator StringIfNotFormattableStringAdapter(FormattableString fs)
вызывает вызов Log($"Hello")
стать неоднозначным?
Потому что при удалении этого оператора второе правило («неявное преобразование из FormattableString
в StringIfNotFormattableStringAdapter
существует»). s ") прерывается, и теперь компилятор не может определить лучшую цель преобразования. Это приводит к неоднозначности для компилятора, и возникает ошибка компиляции.