Ошибка компилятора C#? Почему не делает этой неявной пользовательской компиляции преобразования?

CultureInfo. CurrentCulture. TextInfo. ToTitleCase ("мое имя");

возвраты ~ Мое Имя

, Но проблема все еще существует с именами как McFly, как указано ранее.

32
задан John Saunders 30 July 2009 в 20:04
поделиться

2 ответа

По-видимому, неявные пользовательские преобразования не работают, когда один из типов является интерфейсом. Из спецификаций C #:


6.4.1 Разрешенные определяемые пользователем преобразования

C # разрешает декларировать только определенные определяемые пользователем преобразования. В частности, невозможно переопределить уже существующее неявное или явное преобразование. Для заданного исходного типа S и целевого типа T, если S или T являются типами, допускающими значение NULL, пусть S0 и T0 ссылаются на их базовые типы, в противном случае S0 и T0 равны S и T соответственно. Классу или структуре разрешается объявлять преобразование из исходного типа S в целевой тип T, только если выполняются все следующие условия:

  • S0 и T0 - разные типы.
  • Либо S0, либо T0 - это класс или тип структуры, в котором происходит объявление оператора.
  • Ни S0, ни T0 не являются типами интерфейса .
  • За исключением пользовательских преобразований, преобразование не существует из S в T или из T в S.

В вашем первом методе оба типа не являются типами интерфейса, поэтому определенное пользователем неявное преобразование работает.

Спецификации не очень ясны, но мне кажется, что если один из задействованных типов является типом интерфейса, компилятор не Я даже не пытаюсь найти какие-либо определенные пользователем неявные преобразования.

30
ответ дан 27 November 2019 в 20:44
поделиться

(Продолжение комментариев к принятому ответу.)

Да, это очень, очень запутанная часть спецификации. Все, что касается "охватывающих типов", в частности, глубоко ошибочно. Я уже несколько лет пытаюсь найти время, чтобы полностью переписать весь этот раздел во что-то более связное, но это никогда не было достаточно высоким приоритетом.

По сути, у нас есть противоречие; мы говорим , что не существует определяемых пользователем неявных преобразований с участием интерфейсов, но очевидно, что в данном случае это не так; существует определяемое пользователем неявное преобразование из IC в Foo , переопределить уже существующий неявный или явное преобразование.

Вот что движет всем этим; желание не позволить вам даже подумать, что вы проводите тест типа, сохраняющий представление, когда на самом деле вы вызываете определяемый пользователем метод. Рассмотрим, например, этот вариант:

interface IBar {}
interface IFoo : IBar {}
class Foo<T> : IFoo
{
   public static explicit operator Foo<T>(T input) { whatever }
}
class Blah : Foo<IBar> {}
...
IBar bar = new Blah();  
Foo<IBar> foo = (Foo<IBar>)bar;

Теперь вызывает ли это явное пользовательское преобразование или нет? Объект действительно является производным от Foo, так что можно надеяться, что это не так; это должен быть простой тест типа и присвоение ссылки, а не вызов вспомогательного метода. Приведение к значению интерфейса всегда рассматривается как проверка типа, потому что почти всегда возможно, что объект действительно относится к этому типу и действительно реализует этот интерфейс. Мы не хотим отказать вам в возможности сделать дешевое преобразование с сохранением репрезентации.

24
ответ дан 27 November 2019 в 20:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: