いくつかのこと。
まず、条件演算子は三項演算子であり、三項演算子ではありません。
次に、コードサンプルでは、同等であることが意図されている2つのコードサンプルは次のようになっていないことに注意してください。
short foo;
if (isValid)
foo = -1;
else
getFoo();
と同じではありません
short foo = isValid ? (short)-1 : getFoo();
isValidがfalseの場合、前者はfooを未割り当てのままにします。後者は、isValidの値に関係なくfooを割り当てます。
私はあなたが意味したと思います
short foo;
if (isValid)
foo = -1;
else
foo = getFoo();
さらに、getFoo()はshortを返します。
問題は、型キャストなしの条件演算子での変換が違法であるのに、ifステートメントの結果が合法である理由です。
仕様のセクション6.1.9には次のように記載されているため、ifステートメントでは合法です。
int型の定数式は、定数式の値が宛先型の範囲内であれば、sbyte、byte、short、ushort、uint、またはulong型に変換できます。
-1は、shortの範囲にあるint型の定数式であるため、暗黙的にshortに変換できます。
では、なぜ条件式は偽物なのですか?
最初に明確に確立する必要があるのは、条件式のタイプは、コンテキストからではなく、その内容から決定されるという規則です。割り当ての右側にある式のタイプは、割り当てられているものに依存しません。あなたが持っていたとしましょう
short M(short x){...}
int M(int x){...}
short y = M(-1);
オーバーロードの解決で「-1はintであるため、通常はM(int)を選択しますが、そうでない場合は割り当てが行われないため、代わりにM(short)を選択します」とは思わないでしょう。仕事だ」過負荷の解決は、結果がどこに行くのかについて何も知りません。呼び出しのコンテキストに基づくのではなく、与えられた引数に基づいて、適切なオーバーロードが何であるかを理解することが仕事です。
条件式のタイプの決定は同じように機能します。行き先の型ではなく、式に含まれる型を調べます。
OK、これがshortに割り当てられているという事実は、式のタイプを決定するためには無関係であることがわかりました。しかし、それでも「条件式の型が短いのではなくintであるのはなぜですか?」という疑問が残ります。
それはとても良い質問です。スペックに行きましょう。
?:演算子の2番目と3番目のオペランドxとyは、条件式のタイプを制御します。
タイプがXで、タイプがYの場合、次のようになります。
XからYへの暗黙の変換が存在するが、YからXへの変換は存在しない場合、Yは条件式のタイプです。
YからXへの暗黙の変換が存在するが、XからYへの変換は存在しない場合、Xは条件式のタイプです。
そうしないと、式の種類を判別できず、コンパイル時エラーが発生します。
この場合、オペランドは両方とも型を持っています。(「xに型がある場合...」に関する言い回しは、nullまたはラムダが含まれている場合です。これらには型がありません!)最初のオペランドはint型で、2番目のオペランドは短いタイプ。
shortからintへの暗黙の変換は存在しますが、intからshortへの変換は存在しません。したがって、条件式のタイプはintであり、shortに割り当てることはできません。
さて、このアルゴリズムはそれができるほど良くはないと言うことができます。アルゴリズムを非常に複雑にして、2つの可能な「候補」タイプが存在するすべてのケースを処理することができます。この場合、特定の式と見なすと、両方のブランチがintとshortの両方に変換可能であるため、intとshortの両方がもっともらしい候補です。単に型を持つのではなく。その場合、2つのタイプのうち小さい方が好ましいタイプであると言えます。
(C#では、2つのタイプの一般的な方が良いタイプであると言うことがありますが、この場合は、より具体的なものを選択する必要があります。残念ながら、この特定の設計の側面では言語に一貫性がありません。常により具体的なものを選択しますが、それが今や重大な変化となる型推論のシナリオがあります。)
2006年にそれを行うことを検討しました。LINQが複数のタイプから選択でき、1つを「最良」として選択する必要がある状況を処理する動作を設計するときに、条件演算子はすでにこの問題を解決する必要があることに気付きました。さらに、C#2では、仕様に従って実際に実装されていませんでした。これについては長い議論があり、条件演算子の仕様にいくつかの小さな変更を加えて、実装された(そして望ましい)動作にさらに一致させることになりました。ただし、選択できるタイプがいくつかある場合は、アルゴリズムを微調整して2つの可能なタイプのうち小さい方を使用するという大きな変更は行わないことにしました。
この問題に関するいくつかの考察については、2006年の私の投稿を参照してください。