Вопрос относительно неявных преобразований в спецификации языка C #

StackOverflow https://stackoverflow.com/questions/3736789

Вопрос

Раздел 6.1 Неявные преобразования определяет ан Преобразование личности таким образом:

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

Теперь, какова цель таких приговоров, как эти?

(В §6.1.6 Неявные ссылочные преобразования)

Неявная ссылочная преобразования:

  • [...]
  • От любого Справочный тип к А. Справочный тип T Если у него неявная идентификация или ссылочное преобразование в Справочный тип T0 а также T0 имеет преобразование личности в T.

а также:

(В §6.1.7 преобразования бокса)

  • Тип значения имеет преобразование бокса в тип интерфейса I Если у него есть конвертация бокса в тип интерфейса I0 а также I0 имеет преобразование личности в I.

Первоначально они кажутся избыточными (тавтологичными). Но они должны быть там с целью, так почему же они там?

Можете ли вы привести пример двух типов T1, T2 Такое это T1 было бы нет быть неявно конвертируемым для T2 Если это не для вышеупомянутых пунктов?

Это было полезно?

Решение

Раздел 4.7 Спецификации отмечает, что есть преобразование идентичности из Foo<dynamic> к Foo<object> наоборот. Часть указанного вами спецификации написана, чтобы убедиться, что этот случай обрабатывается. То есть, если есть неявное эталонное преобразование от t до C<object, object> Тогда есть также неявное эталонное преобразование в C<object, dynamic>, C<dynamic, object> а также C<dynamic, dynamic>.

Можно разумно указать, что (1) намерение этих фраз не одолевало - отсюда свой вопрос - и сбивает с толку, а (2), что раздел по преобразованиям личности должен пересекать раздел на динамические преобразования и (3) фразы Таким образом, в спецификации усложняют его к выполнению специалиста, чтобы четко перевести спецификационный язык в реализацию. Как узнать, существует ли какой-нибудь такой тип? Спецификация не должна указывать точные алгоритмы, но было бы неплохо, если он дал больше руководства.

Спецификация, к сожалению, не идеальный документ.

Другие советы

Обновление 22-SEP-2010:

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


Обновление 19-SEP-2010:

В вашем комментарии:

T] его не имеет смысла.

Черт, Тимви, вы говорите, что много. Отказ Но все в порядке, то; Ты поставил меня на оборону, так что здесь идет!

Отказ от ответственности: у меня есть точно нет осмотрел спецификацию так же тесно, как у вас есть. Основываясь на некоторых ваших последних вопросах, в последнее время вы немного смотрели в него. Это, естественно, собирается сделать вас более знакомы с большим количеством деталей, чем большинство пользователей на так; Так что это, как и большинство ответов, вы, вероятно, получите от кого-либо, кроме Eric Lippert, могут не удовлетворить вас.

Разные помещения

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

Ваш ответ, однако, должен был повторять Ваше предположение: «Если предложения действительно избыточны, тогда они только путают читателя и ничего не уточняют».

(Мне нравится, как вы поставили в качестве представителя для всех читателей спецификации там, кстати.)

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

Цель Преобразование личности определение

При первом взгляде это определение кажется довольно лишним; Разве это не просто сказать, что экземпляр любого типа T - это конвертируемый ... ну, чтобы T? Да это так. Но я предполагаю, что целью этого определения является предоставление спецификации с надлежащим словарным запасом для использования концепции Тип идентичности В контексте обсуждения преобразования.

Это позволяет заявлениям о преобразованиях, которые по сути переходят по природе. Первый момент, который вы указали из спецификации в качестве примера тавтологического заявления, попадают в эту категорию. Он говорит, что если неявное преобразование определено для некоторого типа (я назову его) к другому типу T0 и т0 имеет преобразование личности в T, то K неявно конвертируется в T. По определению Преобразование личности Приведено выше, «имеет преобразование личности на« действительно означает », является тем же типом, что и». Так что утверждение избыточный.

Но опять же: Преобразование личности Определение существует в первую очередь для оснащения спецификации с формальным языком для описания преобразования без необходимости говорить такие вещи, как "если t0 и T действительно одинаковый тип.

ОК, время для конкретных примеров.

Где существование неявной преобразования мощь не очевидно, чтобы немного Разработчики

Примечание: А. намного лучше Пример был предоставлен Эриком Липпером в его ответ на вопрос. Отказ Я оставляю эти первые два примера как только незначительные подкрепления моей точки. Я также добавил третий пример, который конкретизирует преобразование идентичности, которое существует между object а также dynamic Как указано в ответ Эрика.

Переходное опорное преобразование

Допустим, у вас есть два типа, M а также N, и у вас есть неявное преобразование, определенное так:

public static implicit operator M(N n);

Тогда вы можете написать код так:

N n = new N();
M m = n;

Теперь скажем, у вас есть файл с этим using Заявление вверху:

using K = M;

И тогда у вас есть, позже в файле:

N n = new N();
K k = n;

Хорошо, прежде чем я продолжу, я понимаю, что Это очевидно, чтобы ты а также меня. Но мой ответ, и был с самого начала, что это может нет быть очевидным каждый, и поэтому указывает это - пока избыточный--still имеет а цель.

Это цель Является ли ясно, чтобы кто-нибудь царапал его голову, глядя на этот код, это законно. Ан. неявное преобразование существует от n до м, а Преобразование личности существует от m до k (т.е. m и k - тот же тип); так что неявное преобразование существует от N на K. Это не только что логично (хотя это может быть логично); Это прямо там в спецификации. Отказ В противном случае можно по ошибке поверить, что будет необходимо что-то вроде следующее:

K k = (M)n;

Очевидно, это не так.

Переходное преобразование бокса

Или взять тип int. Отказ Ан. int может быть в штучной упаковке как IComparable<int>, правильно? Так что это законно:

int i = 10;
IComparable<int> x = i;

Теперь рассмотрим это:

int i = 10;
IComparable<System.Int32> x = i;

Опять таки, да, это может быть очевидный Вам, мне, и 90% всех разработчиков, которые могут когда-либо наткнуться на него. Но для этого тонкого меньшинства, которые не видят это прямо сейчас: Конверсия бокса существует из int к IComparable<int>, и ан Преобразование личности существует из IComparable<int> к IComparable<System.Int32> (т.е. IComparable<int> а также IComparable<System.Int32> такие же тип); так что конвертация бокса существует из int к IComparable<System.Int32>.

Конверсия с участием dynamic тип

Я собираюсь заимствовать от моего эталонного преобразования выше и просто настроить его немного, чтобы проиллюстрировать отношение личности между object а также dynamic В версии 4.0 спецификации.

Скажем, у нас есть типы M<T> а также N, и определили где-то следующее неявное преобразование:

public static implicit operator M<object>(N n);

Тогда следующее является законным:

N n = new N();
M<dynamic> m = n;

Ясно, что вышеизложенное гораздо меньше очевидный чем два предыдущих примера. Но вот вопрос миллиона долларов: будет выше еще Будьте законным, даже если выдержки из специфики цитируются в вопросе, не существовали? (Я собираюсь позвонить на эти выдержки Q. для краткости.) Если ответ да, то Q. на самом деле избыточно. Если нет, то это не так.

Я верю, что ответ да.

Рассмотреть определение Преобразование личности, определенный в разделе 6.1.1 (я включаю весь раздел здесь, как это довольно коротко):

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

Потому что object а также dynamic считаются эквивалентными, существует преобразование идентичности между object а также dynamic, и между построенными типами, которые одинаковы при замене всех возникновений dynamic с участием object. Упор мой

(Эта последняя часть также включена в раздел 4.7, что определяет dynamic тип.)

Теперь давайте посмотрим на код снова. В частности, я заинтересован в этой одной линии:

M<dynamic> m = n;

Законность этого заявления (игнорирование Q. - Помните, что обсуждаемая проблема - это гипотетическая законность вышеуказанного заявления если Q. сделал нет существовать), так как M<T> а также N являются пользовательскими типами, зависит от существования пользовательского неявного преобразования между N а также M<dynamic>.

Существует неявное преобразование от N к M<object>. Отказ По разделу специфики выше указанного выше, существует преобразование личности между M<object> а также M<dynamic>. Отказ По определению Преобразование личности, M<object> а также M<dynamic> тот же тип.

Так, так же, как в первых двух (более очевидных) примерах, я верю, что это правда, что неявное преобразование существует из N к M<dynamic> даже без принятия Q. в учетную запись, так же, как это правда, что неявное преобразование существует из N к K в первом примере и что конверсия бокса существует из int к IComparable<System.Int32> Во втором примере.

Без Q., это гораздо менее очевидно (следовательно Q.существование); Но это не делает его ложным (т.е. Q. не является необходимо Для этого поведения будет определено). Это просто делает его менее очевидным.

Заключение

Я сказал в своем первоначальном ответе, что это «очевидное» объяснение, потому что мне казалось, что вы лаете не на том дереве. Вы изначально поставили эту проблему:

Можете ли вы привести пример двух типов T1, Т.2 Такое, что Т.1 не будет неявно конвертируемы в T2 Если это не для вышеупомянутых пунктов?

Никто не собирается удовлетворить этот вызов, Timwi, потому что это невозможно. Возьмите первый выдержку по поводу опорных преобразований. Говорят, что тип k неявно конвертируется к типу T, если он неявно конвертируется в T0 и т0 Так же, как T. деконструирует это, положить его вместе, и вы остались с очевидной тавтологией: k неявно конвертируется в T, если он неявно конвертируется в T. Делает ли это какие-либо новые неявные преобразования? Конечно, нет.

Так что комментарий Бен Voigt был правильным; Возможно, эти моменты, о которых вы спрашиваете, было бы лучше поместить в сноски, а не в теле текста. В любом случае, мне ясно, что они являются избыточный и так начинать с предпосылки они не могут быть избыточными, или они не будут там это приступить к поручению дурака. Будьте готовы принять, что избыточное заявление может все еще может пролить свет на концепцию, которая может быть не очевидна для всех, и станет легче принять эти заявления для того, что они есть.

Избыточный? да. Тавтологичный? да. Бессмысленно? В мой Мнение, нет.

* Очевидно, у меня не было никакой части в написании спецификации языка C #. Если бы я сделал, этот ответ будет намного более авторитетным. Как это так, он просто представляет собой слабую попытку одного парня, чтобы понять довольно сложный документ.


Оригинальный ответ

Я думаю, что вы (возможно, намеренно) с видом на самый очевидный ответ здесь.

Рассмотрим эти два предложения в вашем вопросе:

(1) Первоначально они кажутся избыточными (тавтологичными). (2) Но они должны быть там с целью, так почему же они там?

Для меня воздействие этих двух приговоров вместе состоит в том, что тавтологичное заявление служит никакой цели. Но только потому, что заявление логически следует из установленных помещений, что не делает это очевидно для всех. Другими словами, даже если (1) правда, ответ на (2) может просто быть: Чтобы понять описанное поведение, чтобы кто-нибудь читал спецификацию.

Теперь вы можете утверждать, что даже если что-то не очевидный, Он все еще не принадлежит спецификации, если оно обеспечивает избыточное определение. Для этого потенциального возражения я могу только сказать: быть реалистичным. Не очень практично (на мой взгляд) расчесывается через документ, развязав все заявления, которые просто заявляют о фактах, которые могли быть выведены из предварительных утверждений.

Если это мы Обычная практика, я думаю, вы найдете много литературы там - не только спецификации, но исследовательские документы, статьи, учебники и т. Д. - Были бы намного короче, плотнее, и труднее понять.

Итак: Да, возможно, они избыточны. Но это не отрицает их цель.

Преобразование личности преобразует от любого типа к тому же типу. Отказ Это преобразование существует так, что сущность, которая уже имеет требуемый тип можно сказать, чтобы быть конвертированным к этому типу.

Это говорит, что в C #, 1 == 1; Spade - это лопата. Это основа присвоения ссылки на объект переменной одного и того же типа; Если переменная набратая T1 и один напечатанный T2, находятся на реальности оба лопата, можно присвоить другому, без необходимости явного отбрасывания одного в качестве лопаты. Представьте себе вариант C #, где назначения должны были выглядеть так:

Spade mySpade = new Spade();
Spade mySpade2;

mySpade2 = (Spade)mySpade; //explicit cast required

Кроме того, «идентичность» в области математики утверждает, что выражение, которое оценивает к результату, данному набору входов, эквивалентно другому выражению, которое вызывает тот же результат, учитывая одинаковые входы. В программировании это означает, что выражение или функция, которая оценивает экземпляр типа, эквивалентна этому типу, без явного преобразования. Если это не удержало, потребуется следующий код:

public int myMethod() { /*Do something*/ }
...
int myInt = (int)myMethod(); //required even though myMethod() evals to an int.
...
int myInt = (int)(1 + 2); //required even though 1, 2, and 1+2 eval to an int.

Второе правило в основном говорит, что тип значения может быть назначен переменной элементами на классе, если частично, переменная элемента (в корпусе по определению, поскольку ее контейнер представляет собой эталонный тип), объявлен одинаковым типом. Если это правило не было указано, теоретически, теоретически, версия C # может существовать, в которой типы чистых значений должны быть явно преобразованы в свой справочный аналог, чтобы хранить в качестве переменной элемента в классе. Представьте, например, версия C #, в которой синие типы ключевых слов (INT, FLOAT, десятичное число) и светло-голубые названия классов (INT32, FLOAT, десятичная, десятичная) упомянули два очень разных, только явно-конвертируемых типах и INT , поплавок, десятичные и т. Д. Были не законным в качестве типов переменной участника, потому что они не были ссылочными типами:

public class MyClass
{
  Int32 MyBoxedValueType; //using "int" not legal
}

...

MyClass myClass = new MyClass();
int theInt = 2;

myClass.MyBoxedValueType = (Int32)theInt; //explicit cast required

Я знаю, что это звучит глупо, но на некотором уровне эти вещи должны быть известны, а на компьютерах вы должны указать все. Прочитайте команду хоккея США для хоккея на хоккей когда-нибудь; Самое первое правило в книге заключается в том, что игра играется на поверхности льда. Это один из окончательных «ну Дюхс», но и фундаментальная истина игры, которая должна быть понята для любого другого правила, чтобы иметь смысл.

Пусть это так, что код гарантирует пропуск, когда называется Convert.ChangeType(client, typeof(Client)) Независимо от того, если IConvertible реализован.

Смотреть в источник ChangeType от mscorlib с отражателем и обратите внимание на условия, на которые value возвращается как есть.

Помнить А. = Оператор не является преобразованием, просто ссылочный набор. Так что код вроде Client client_2 = client_1 не выполняет никаких неявных преобразований. Если идентификация неявной преобразования объявляется, то ошибка CS0555 выпущен.

Я думаю, что SPEC говорит, пусть C # Compiler обрабатывает такие случаи, и, таким образом, точка нет Вручную попробуйте определить преобразования личности.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top