これは C# の設計による方法であり、実際には C/C++ までさかのぼります - 後者はオペランドを に昇格させますが、C# にはありませんが、変換は暗黙的であるint
ため、通常は気付かないだけです。int -> char
これは、どちらか一方だけに適用されるのではなく、すべての算術オペランドとビット演算オペランドに適用されます。たとえば、2 つの s を|
追加すると、同様に が得られます。ここで仕様の関連部分を引用します。byte
int
2 進数の昇格は、定義済みの +、–、*、/、%、&、|、^、==、!=、>、<、>=、および <= 2 項演算子のオペランドに対して発生します。バイナリ数値昇格では、暗黙的に両方のオペランドが共通の型に変換されます。非関係演算子の場合、この型は演算の結果の型にもなります。2 進数の昇格は、次の規則をここに表示されている順序で適用することで構成されます。
一方のオペランドが decimal 型の場合、もう一方のオペランドは decimal 型に変換されます。または、もう一方のオペランドが float または double 型の場合は、コンパイル時エラーが発生します。
それ以外の場合、いずれかのオペランドが double 型の場合、もう一方のオペランドは double 型に変換されます。
それ以外の場合、いずれかのオペランドが float 型の場合、もう一方のオペランドは float 型に変換されます。
それ以外の場合、いずれかのオペランドが ulong 型の場合、もう一方のオペランドは ulong 型に変換されます。または、もう一方のオペランドが sbyte、short、int、または long 型の場合は、コンパイル時エラーが発生します。
それ以外の場合、いずれかのオペランドが long 型の場合、もう一方のオペランドは long 型に変換されます。
それ以外の場合、一方のオペランドが uint 型で、もう一方のオペランドが sbyte、short、または int 型の場合、両方のオペランドが long 型に変換されます。
それ以外の場合、いずれかのオペランドが uint 型の場合、もう一方のオペランドは uint 型に変換されます。
それ以外の場合、両方のオペランドが int 型に変換されます。
これの正確な根拠はわかりませんが、1つ考えることができます。特に算術演算子の場合、関係する型を注意深く検討したときに何らかの意味があったとしても、人々が(byte)200 + (byte)100
突然 に等しくなることは少し驚くかもしれません。44
一方、int
は一般に、ほとんどの典型的な数値の算術演算に「十分に適した」型と見なされているため、両方の引数を に昇格させることint
で、ほとんどの一般的なケースで一種の「正常に機能する」動作が得られます。
このロジックがビットごとの演算子にも適用された理由については、ほとんど一貫性のためだと思います。これにより、ブール値以外のすべてのバイナリ型に共通する単一の単純なルールが得られます。
しかし、これはほとんど推測です。Eric Lippert は、少なくとも C# のこの決定の背後にある本当の動機について尋ねる人でしょう (ただし、答えが単に「C/C++ と Java で行われている方法であり、それで十分である」という場合は少し退屈になります)。ルールはそのままであるため、変更する理由はありません」)。