Обновление от 22 сентября 2010 г .:
Я сомневаюсь, что кто-нибудь прочтет это, кроме Тимви. Тем не менее, я хотел бы внести несколько изменений в этот ответ в свете того факта, что новый ответ уже принят, и дискуссия все еще продолжается (по крайней мере, в моем, возможно, воображаемом мире) о том, цитируются ли выдержки из спецификации или нет. технически избыточны. Я не добавляю много, но это слишком существенно, чтобы вписаться в комментарий. Основная часть обновления находится под заголовком «Преобразование с использованием dynamic
типа» ниже.
Обновление от 19 сентября 2010 года:
В вашем комментарии:
[T] его не имеет смысла.
Черт, Тимви, вы говорите, что много . Но тогда все в порядке; Вы поставили меня в оборону, так что здесь!
Отказ от ответственности: я определенно не изучил спецификацию так же внимательно, как и вы. Исходя из некоторых ваших недавних вопросов, кажется, что вы в последнее время довольно много изучали это. Это, естественно, поможет вам узнать больше деталей, чем большинство пользователей SO; так что это, как и большинство ответов, которые вы, вероятно, получите от кого-либо, кроме Эрика Липперта, может вас не удовлетворить.
Разные помещения
Во-первых, предпосылка вашего вопроса заключается в том, что если выделенные утверждения избыточны , то они не служат цели . Мой ответ заключается в том, что избыточные утверждения не обязательно являются бесполезными, если они проясняют то, что не очевидно для всех . Это противоречивые предпосылки. И если мы не можем договориться о посылках, у нас не может быть прямого логического аргумента. Я просто просил вас переосмыслить вашу предпосылку.
Однако ваш ответ был на подтверждение вашей предпосылки: «Если предложения действительно избыточны, то они только смущают читателя и ничего не разъясняют».
(мне, кстати, нравится, что вы представляете себя в качестве представителя для всех читателей спецификации).
Не могу винить вас за то, что вы удерживаете эту позицию, точно. Я имею в виду, это кажется очевидным. И я не привел никаких конкретных примеров в своем первоначальном ответе. Поэтому ниже я постараюсь включить некоторые конкретные примеры. Но сначала позвольте мне сделать шаг назад и предложить, почему эта странная концепция преобразования идентификаторов существует в спецификации в первую очередь.
Цель преобразования идентификатора Определение
На первый взгляд, это определение кажется излишним; разве это не говорит о том, что экземпляр любого типа T может быть преобразован в ... ну, в T? Да, это. Но я предполагаю *, что цель этого определения состоит в том, чтобы предоставить спецификации соответствующий словарь, чтобы использовать концепцию идентичности типов в контексте обсуждения преобразований .
Это позволяет делать заявления о преобразованиях, которые по своей сути являются переходными. Первый пункт, который вы процитировали из спецификации в качестве примера тавтологического утверждения, попадает в эту категорию. В нем говорится, что если для какого-то типа определено неявное преобразование (я назову его K) в другой тип T 0 и T 0 имеет преобразование идентификатора в T, то K неявно преобразуется в T. По определению преобразование идентичности , данное выше, «имеет преобразование идентичности в« действительно означает »того же типа, что и». Таким образом, заявление избыточно .
Но опять же: определение преобразования идентификаторов существует в первую очередь для того, чтобы снабдить спецификацию формальным языком для описания преобразований без необходимости произносить такие слова, как "if T 0 и 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;
Хорошо, прежде чем я продолжу, я понимаю, что это очевидно для вас и меня . Но мой ответ таков и был с самого начала, что это может не быть очевидным для каждого , и, следовательно, указание его - в то время как избыточный - все еще имеет цель .
Эта цель заключается в том, чтобы дать понять любому, кто почесывает голову, смотрит на этот код, это законно. неявное преобразование существует из N в M, и преобразование идентичности существует из 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 (здесь я включаю весь раздел, поскольку он довольно короткий):
1212 * *
Преобразование идентичности преобразуется из любого типа в тот же тип. Это преобразование существует таким образом, что объект, который уже имеет требуемый тип, можно назвать конвертируемым в этот тип.
Поскольку object
и dynamic
считаются эквивалентными, существует преобразование идентичности между object
и dynamic
, и между созданными типами, которые одинаковы при замене всех вхождений dynamic
на object
. [Акцент мой]
(Эта последняя часть также включена в раздел 4.7, который определяет тип dynamic
.)
Теперь давайте снова посмотрим на код. В частности, меня интересует эта строка:
M<dynamic> m = n;
Законность этого утверждения (без учета Q - помните, что обсуждаемая проблема - это гипотетическая законность приведенного выше утверждения , если Q did не существует), поскольку M<T>
и N
являются пользовательскими типами, зависит от наличия определенного пользователем неявного преобразования между N
и M<dynamic>
.
Существует неявноепреобразование из N
в M<object>
.В разделе спецификации, указанном выше, существует преобразование идентичности между M<object>
и M<dynamic>
.По определению преобразование идентичности , M<object>
и M<dynamic>
имеют одинаковый тип .
Итак, так же, как в первых двух (более очевидных) примерахЯ считаю, что это правда, что неявное преобразование существует из N
в M<dynamic>
даже без учета Q с учетом , точно так же, как и то, что неявное преобразование существует из *С 1267 * до K
в первом примере, и что во втором примере существует преобразование в боксы с int
до IComparable<System.Int32>
.
Без Q , это гораздо менее очевидно (отсюда Q существование); но это не делает его ложным (т. Е. Q не необходимо для определения этого поведения).Это просто делает его менее очевидным.
Заключение
Я сказал в своем первоначальном ответе, что это «очевидное» объяснение, потому что мне показалось, что вы лаете не на то дерево.Вы изначально поставили эту задачу:
Можете ли вы привести пример двух типов: T 1 , T 2 , таких что T 1 не был бы неявно преобразован в T 2 , если бы не вышеприведенные абзацы?
Никто не собирается отвечать на этот вызов, Тимви, потому что это невозможно.Возьмите первый отрывок о ссылочных конверсиях.Это говорит о том, что тип K неявно преобразуется в тип T, если он неявно преобразуется в T 0 , а T 0 совпадает с T. Разобрать его, собрать его обратно вместеи у вас остается очевидная тавтология: K неявно преобразуется в T, если он неявно преобразуется в T. Вводит ли это какие-либо новые неявные преобразования?Конечно нет.
Так что, возможно, комментарий Бена Фойгта был верным;возможно, эти вопросы, о которых вы спрашиваете, лучше бы поместить в сноски, а не в текст.В любом случае, для меня ясно, что они являются избыточными, и поэтому, если исходить из предпосылки , они не могут быть избыточными, иначе их не будет - это начатьпоручение дуракаБудьте готовы принять, что избыточное утверждение может пролить некоторый свет на концепцию, которая может быть не очевидна для всех, и станет легче принять эти утверждения такими, какие они есть.
Избыточный?Да.Тавтология?Да.Бессмысленно?По моему мнению, нет.
* Очевидно, я не принимал никакого участия в написании спецификации языка C #.Если бы я это сделал, этот ответ был бы намного более авторитетным.На самом деле это просто слабая попытка одного парня разобраться в довольно сложном документе.
Оригинальный ответ
Я думаю, вы (возможно, намеренно) упускаете из видусамый очевидный ответ здесь.
Рассмотрите два предложения в вашем вопросе:
(1) Изначально они кажутся излишними (тавтологичными). (2) Но они должны быть там с определенной целью, так почему они там?
Для меня смысл этих двух предложений в том, что тавтологическое утверждение не служитцель.Но только потому, что утверждение логически следует из установленных предпосылок, это не делает его очевидным для всех.Другими словами, даже если (1) истинно, ответ на (2) может быть просто: , чтобы сделать описанное поведение понятным для любого, кто читает спецификацию .
Теперь вы можете утверждать, что даже если что-то не является очевидным , оно все равно не входит в спецификацию, если оно предоставляет избыточное определение. На это потенциальное возражение я могу только сказать: будь реалистом. На мой взгляд, не очень практично прочесывать документ, в котором отбрасываются все утверждения, в которых просто указываются факты, которые могли быть выведены из предыдущих заявлений.
Если бы это было обычной практикой, я думаю, что вы найдете много литературы - не только спецификации, но и научные статьи, статьи, учебники и т. Д. короче, плотнее и сложнее для понимания.
Итак: да, возможно, они излишни. Но это не отменяет их цели.