2010 年 9 月 22 日の更新:
ティムウィ以外にこれを読む人はいないだろう。それでも、新しい回答が受け入れられ、仕様の引用された抜粋が技術的に冗長です。私は多くを追加していませんが、コメントに収まるにはあまりにも重要です. 更新の大部分は、以下の「型を含む変換」dynamic
という見出しの下にあります。
2010 年 9 月 19 日の更新:
あなたのコメントで:
[T]これは意味がありません。
くそー、ティムウィ、あなたはそれをたくさん言います。でも大丈夫です。あなたは私を守備に置いたので、ここに行きます!
免責事項:私は間違いなく、あなたほど詳細に仕様を調べていません. あなたの最近の質問のいくつかに基づいて、あなたは最近それをかなり調べているようです. これにより、SO のほとんどのユーザーよりも多くの詳細に慣れることができます。したがって、これは、Eric Lippert 以外から受け取る可能性が高いほとんどの回答と同様に、満足できない場合があります。
別の施設
まず、あなたの質問の前提は、強調表示されたステートメントが冗長である場合、それらは何の役にも立たないということです。私の回答の前提は、冗長なステートメントが、誰にとっても明らかではない何かを明確にする場合、必ずしも目的がないわけではないということです。これらは相反する前提です。そして、前提に同意できない場合、単純な論理的議論はできません。私はただ、あなたの前提を再考するようにお願いしただけです。
しかし、あなたの回答は、あなたの前提を繰り返すことでした。「文が本当に冗長である場合、それらは読者を混乱させるだけで、何も明確にしません。」
(ちなみに、仕様のすべての読者の代表として自分を設定した方法が気に入っています。)
あなたがこのポジションを保持していることを責めることはできません。つまり、それは明らかなようです。また、元の回答では具体的な例を挙げていませんでした。そこで、以下に具体的な例をいくつか含めてみます。しかし、最初に、一歩下がって、なぜこの奇妙なID 変換の概念が仕様に存在するのかについて、私の見解を述べさせてください。
恒等変換定義の目的
一見すると、この定義は不必要に思えます。任意の型 T のインスタンスが ... まあ、T に変換可能であると言っているだけではありませんか? はい、そうです。しかし、この定義の目的は、変換を議論するコンテキストで型同一性の概念を利用するための適切な語彙を仕様に提供することであると私は仮定します* 。
これにより、本質的に推移的な変換に関するステートメントが可能になります。トートロジーステートメントの例として仕様から引用した最初のポイントは、このカテゴリに分類されます。ある型 (K と呼びます) から別の型 T 0への暗黙の変換が定義されていて、T 0 が T への恒等変換を持つ場合、K は暗黙的に T に変換可能であるということです。与えられた恒等変換の定義により、上記の「同一の型に変換されている」は、実際には「と同じ型である」ことを意味します。したがって、ステートメントは冗長です。
繰り返しになりますが、恒等変換の定義は、「T 0と T が本当に同じ型である場合」などのことを言わなくても、変換を記述するための正式な言語を仕様に装備するために最初に存在します。
では、具体例の時間です。
一部の開発者にとって、暗黙的な変換の存在が明らかでない可能性がある場合
注: Eric Lippertの質問への回答で、はるかに優れた例が提供されています。これらの最初の 2 つの例は、私の要点を補強するためのものとして残しておきます。エリックの回答で指摘されているように、との間に存在する ID 変換を具体化する 3 番目の例も追加しました。object
dynamic
推移参照変換
と の 2 つの型が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;
OK、先に進む前に、これはあなたにも私にも明らかなことだと思います。しかし、私の答えは、それは誰にとっても明らかではないかもしれないということであり、最初からそうでした.
その目的は、そのコードを見て頭を悩ませている人に、それが合法であることを明確にすることです。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
型を含む変換
上記の参照変換の例から借用し、仕様のバージョン 4.0 でのobject
との同一関係を説明するために少し調整します。dynamic
M<T>
型とN
があり、次の暗黙の変換をどこかに定義したとしましょう。
public static implicit operator M<object>(N n);
次に、以下が合法です。
N n = new N();
M<dynamic> m = n;
明らかに、上記は前の 2 つの例よりもはるかに明白ではありません。しかし、ここに百万ドルの質問があります: 質問で引用された仕様からの抜粋が存在しなくても、上記は依然として合法でしょうか? (簡潔にするために、これらの抜粋をQと呼びます。) 答えが「はい」の場合、Qは実際には冗長です。いいえの場合、そうではありません。
答えはイエスだと思います。
セクション 6.1.1 で定義されている ID 変換の定義を考えてみましょう(非常に短いため、セクション全体をここに含めます)。
ID 変換は、任意の型から同じ型に変換します。この変換は、必要な型を既に持っているエンティティがその型に変換可能であると言えるように存在します。
object
とは同等であると見なされるため、 と の間、および のすべての発生をで置き換えると同じである構築された型の間でdynamic
同一性変換が行われます。[鉱山を強調]object
dynamic
dynamic
object
(この最後の部分は、タイプを定義するセクション 4.7 にも含まれていますdynamic
。)
では、もう一度コードを見てみましょう。特に、次の 1 行に興味があります。
M<dynamic> m = n;
とはカスタム型であるため、このステートメントの正当性は ( Qを無視します -- 議論されている問題は、Qが存在しない場合 の上記のステートメントの仮説上の正当性であることに注意してください)、との間のユーザー定義の暗黙的な変換の存在に依存します。.M<T>
N
N
M<dynamic>
N
からへの暗黙の変換が存在しM<object>
ます。上記の仕様のセクションでは、 と の間に恒等変換がM<object>
ありM<dynamic>
ます。恒等変換の定義により、M<object>
とM<dynamic>
は同じ型です。
したがって、最初の 2 つの (より明白な) 例と同様に、 Q を考慮せずに から への暗黙的な変換が存在することは正しいと思いN
ます。2 番目の例では、からへのボックス化変換が存在します。M<dynamic>
N
K
int
IComparable<System.Int32>
Qがなければ、これはあまり明白ではありません (したがって、Qの存在)。しかし、それは偽にはなりません(つまり、この動作を定義するためにQは必要ありません)。目立たなくするだけです。
結論
元の回答で、これは「明白な」説明だと言いました。なぜなら、あなたは間違った木を吠えているように思えたからです。あなたは最初にこの課題を提起しました:
上で引用したパラグラフがなければ、 T 1が暗黙的に T 2に変換できないような 2 つの型 T 1、 T 2の例を挙げていただけますか?
ティムウィ、誰もこの挑戦に立ち向かわないだろう、それは不可能だからだ。参照変換に関する最初の抜粋を見てみましょう。型 K が T 0に暗黙的に変換可能であり、T 0が T と同じ場合、型 K は型 T に暗黙的に変換可能であると言っています。これを分解し、元に戻すと、明らかなトートロジーが残ります: K暗黙的に T に変換可能な場合、暗黙的に T に変換可能です。これにより、新しい暗黙的な変換が導入されますか? もちろん違います。
したがって、おそらく Ben Voigt のコメントは正しかったでしょう。あなたが尋ねているこれらのポイントは、テキストの本文ではなく、脚注に配置する方が適切だったかもしれません. いずれにせよ、それらが冗長であることは明らかであり、前提から始めると、冗長になることはありません。冗長なステートメントが、誰にとっても明らかではないかもしれない概念に光を当てる可能性があることを喜んで受け入れてください。そうすれば、これらのステートメントが何であるかを受け入れやすくなります。
冗長?はい。互変異性?はい。無意味?私の意見では、いいえ。
*明らかに、私は C# 言語仕様の作成に関与していません。もしそうなら、この答えはもっと権威のあるものになるでしょう。現状では、かなり複雑な文書を理解しようとする一人の人間の弱々しい試みを表しているにすぎません。
元の答え
ここで最も明白な答えを見落としていると思います(おそらく意図的に)。
質問の次の 2 つの文を検討してください。
(1)最初は重複しているように見えます (トートロガス)。(2)しかし、それらは目的のためにそこにあるに違いありません。
私にとって、これら 2 つの文を一緒にすると、同義語のステートメントは何の役にも立たないということになります。しかし、ステートメントが確立された前提から論理的に従うからといって、それが誰にとっても明らかであるとは限りません. 言い換えれば、(1)が正しいとしても、 (2)に対する答えは単に:記述された動作を仕様を読んでいる人に明確にするためです。
ここで、何かが明白でなくても、冗長な定義を提供している場合、それは仕様に属さないと主張するかもしれません。この潜在的な反論に対して、私が言えることは、現実的であることだけです。以前の声明から推測できた可能性のある事実を単に述べているだけのすべての声明を除外してドキュメントをくまなく調べることは、(私の意見では)実際には実際的ではありません。
もしこれが一般的な慣習であったなら、仕様だけでなく、研究論文、記事、教科書などの多くの文献がそこにあると思います.はるかに短く、密度が高く、理解するのがより困難になるでしょう. .
だから:はい、おそらくそれらは冗長です。しかし、それは彼らの目的を否定するものではありません。