私はLINQPadでいくつかのコードゴルフを見ていて、なぜだろうと思っています:
int c;
string o;
o+=c;//this works
o+=P==2?"."+c:c;//this doesn't
o+=P==2?"."+c:""+c;//this does
主に、最初のものが機能し、2番目のものが「'string'と'int'の間の暗黙の変換なし」エラーをスローする理由。
私はLINQPadでいくつかのコードゴルフを見ていて、なぜだろうと思っています:
int c;
string o;
o+=c;//this works
o+=P==2?"."+c:c;//this doesn't
o+=P==2?"."+c:""+c;//this does
主に、最初のものが機能し、2番目のものが「'string'と'int'の間の暗黙の変換なし」エラーをスローする理由。
文字列の+
演算子はintを受け入れることができ、結果として別の文字列になります。ただし、intからstringへの暗黙的(または明示的)キャストはありません。
三項演算子を使用する場合?:
、両方の「ブランチ」が同じタイプであるか、一方のタイプが暗黙的に他方に変換可能である必要があります。
2番目の例では、+
演算子が実行された後の最初のブランチは文字列ですが、2番目のブランチは単なるintであるため、機能しません。3番目の例では、両方のブランチが文字列であるため、問題ありません。
+=
オペレーターはオペレーターを使用するので+
、最初は実際には次のとおりです。
o = o + c;
コンパイラが実際に作成するのは次のとおりです。
o = String.Concat((object)o, (object)c);
整数はボックスで囲まれ、パラメーターを受け取るConcat
メソッドobject
が呼び出されます。メソッドは両方のToString
パラメーターで呼び出され、文字列値を取得し、連結されます。
最初に整数を文字列に変換すると、コードはより単純になります。
o += c.ToString();
これは次のようになります。
o = String.Concat(o, c.ToString());
2番目のコードでは、条件演算子の型が一致していません。
bool ? string : int
2番目と3番目のオペランドは、3番目のコードのように、同じタイプである必要があります。
bool ? string : string
2番目のコードは実際には次のようになります。
o = String.Concat(
o,
P == 2
? String.Concat((object)".", (object)c)
: c
);
そして3番目のコードは実際には次のようになります。
o = String.Concat(
o,
P == 2
? String.Concat((object)".", (object)c)
: String.Concat((object)String.Empty, (object)c)
);
とにかく、演算子StringBuilder
を使用する代わりに、を使用して文字列を作成することを検討する必要があります。+=
StringBuilder builder = new StringBuilder;
if (P == 2) {
builder.Append('.');
}
builder.Append(c);
2番目の機能しない例では、?:
演算子に一貫性のないタイプがあります。あなたが持っているものは:
o += (P == 2 ? (string) "." + c : (int) c);
(上記の括弧内のタイプは、既存のタイプが何であるかを明確にするためのものであり、別のタイプにキャストするためのものではありません。)
三項演算子の両側は:
同じタイプである必要があります。このため、2番目の例は構文エラーです。空の文字列との連結は文字列に強制c
されるため、3番目の例は機能します。